Hibernate Criteria returns children multiple times with FetchType.EAGER
This is actually the expected behaviour if I understood your configuration correctly.
You get the same Order
instance in any of the results, but since now you are doing a join with the OrderTransaction
, it has to return the same amount of results a regular sql join will return
So actually it should apear multiple times. this is explained very well by the author (Gavin King) himself here:
It both explains why, and how to still get distinct results
Also mentioned in the Hibernate [FAQ][2] :
Hibernate does not return distinct results for a query with outer join fetching enabled for a collection (even if I use the distinct
keyword)? First, you need to understand SQL and how OUTER JOINs work
in SQL. If you do not fully understand and comprehend outer joins in
SQL, do not continue reading this FAQ item but consult a SQL manual or
tutorial. Otherwise you will not understand the following explanation
and you will complain about this behavior on the Hibernate forum.Typical examples that might return duplicate references of the same
Order object:List result = session.createCriteria(Order.class)
.setFetchMode("lineItems", FetchMode.JOIN)
.list();<class name="Order">
...
<set name="lineItems" fetch="join">List result = session.createCriteria(Order.class)
.list();
List result = session.createQuery("select o from Order o left join fetch o.lineItems").list();All of these examples produce the same SQL statement:
SELECT o.*, l.* from ORDER o LEFT OUTER JOIN LINE_ITEMS l ON o.ID = l.ORDER_ID
Want to know why the duplicates are there? Look at the SQL resultset,
Hibernate does not hide these duplicates on the left side of the outer
joined result but returns all the duplicates of the driving table. If
you have 5 orders in the database, and each order has 3 line items,
the resultset will be 15 rows. The Java result list of these queries
will have 15 elements, all of type Order. Only 5 Order instances will
be created by Hibernate, but duplicates of the SQL resultset are
preserved as duplicate references to these 5 instances. If you do not
understand this last sentence, you need to read up on Java and the
difference between an instance on the Java heap and a reference to
such an instance.(Why a left outer join? If you'd have an additional order with no line
items, the result set would be 16 rows with NULL filling up the right
side, where the line item data is for other order. You want orders
even if they don't have line items, right? If not, use an inner join
fetch in your HQL).Hibernate does not filter out these duplicate references by default.
Some people (not you) actually want this. How can you filter them out?Like this:
Collection result = new LinkedHashSet( session.create*(...).list() );
Criteria returns same object several times
I guess the user>computer relation is not set as lazy so it loads up all the computer in a outer join to populate the getComputers from the user
you can use
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
to only iterate trough each entity once
Join Fetch for One To Many relationship is returning same entity multiple times
See the JPA spec 4.4.5.3
SELECT d FROM Department d LEFT JOIN FETCH d.employees WHERE d.deptno = 1
A fetch join has the same join semantics as the corresponding inner or
outer join, except that the related objects specified on the
right-hand side of the join operation are not returned in the query
result or otherwise referenced in the query. Hence, for example, if
department 1 has five employees, the above query returns five
references to the department 1 entity.
Options
- You can add a
DISTINCT
to theSELECT
clause to filter out the
duplicate rows. - Define an
EntityGraph
for the query and add theroles
field to it,
and it will be fetched, meaning you omit the"FETCH JOIN"
from the query. - Mark the
roles
field as EAGER, but this would then apply to all fetching of that field, so likely not desirable.
Related Topics
Integrating Tomcat and Eclipse as a Hot-Deploy Environment
Import Maven Dependencies in Intellij Idea
Convert Existing Eclipse Project to Maven Project
Initializing Multiple Variables to the Same Value in Java
Calculating Distance Between Two Points, Using Latitude Longitude
Upload Files from Java Client to a Http Server
Java Embedded Databases Comparison
How to Use Classes from .Jar Files
Get Domain Name from Given Url
Cannot Create an Array of Linkedlists in Java
Picking a Random Element from a Set
Execute Another Jar in a Java Program
Lambdas: Local Variables Need Final, Instance Variables Don'T
Java: (String[])List.Toarray() Gives Classcastexception
Why Java Inner Classes Require "Final" Outer Instance Variables
Key Bindings VS. Key Listeners in Java
Covariance, Invariance and Contravariance Explained in Plain English