Reputation: 189
I have 2 simple models:
class Parent {
Long id; //auto generated sequence and primary key
String name;
Set<Child> children;
}
class Child {
String name;
Long parent_id; //foreign key
}
I have a hql query like this:
FROM Parent p
left join fetch p.children as children
WHERE p.name = 'John'
'children' is a collection (set) of 'Child' model in Parent model.
If 'John' has 2 children, result of above query gives me list of 2 Parents (same reference) each with 2 children by executing a single query.
I am trying to achieve the same via Criteria API like below:
Criteria c = session.createCriteria(Parent.class);
c.setFetchMode("children", FetchMode.JOIN);
c.createCriteria("children", Criteria.LEFT_JOIN);
c.add(Restrictions.eq("name", "John"));
c.scroll();
With above code, I get the list of 2 parent instances (same reference) with only 1 child element (instead of expected 2) bu executing a single sql query.
What am I doing wrong in api? When I see the generated sql, it is same.
Upvotes: 1
Views: 2206
Reputation: 11535
I had the same issue, and after debugging through the Hibernate code I think it's a Hibernate bug rather than anything you're doing wrong.
It was fixed in this Hibernate issue, but our Criteria was still returning incomplete child collections in scrollable results. I found that in the Loader
class there's some logic that decides whether to use the FetchingScrollableResultsImpl
to handle the rows properly, and on CriteriaLoader
it never does because needsFetchingScroll()
always returns false. However QueryLoader
does use it when a join fetch is used, which is why converting our Criteria into HQL fixed the issue for us.
I intend to file a bug with Hibernate to implement CriteriaLoader.needsFetchingScroll()
.
Upvotes: 1
Reputation: 3889
I have a similar situation, and here is the code that is equivalent (at least in my situation):
Criteria c = session.createCriteria(Parent.class);
c.setFetchMode("children", FetchMode.JOIN);
c.add(Restrictions.eq("name", "John"));
List<Parent> list = c.list();
Iterator<Parent> iter = list.iterator();
I have the impression that the line
c.scroll();
forces a similar behavior to c.setResultTransformer( Criteria.DISTINCT_ROOT_ENTITY );
Upvotes: 0