Bhargava
Bhargava

Reputation: 189

Hibernate Criteria API results not matching HQL results for left join fetch

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

Answers (2)

Nick H
Nick H

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

iliaden
iliaden

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

Related Questions