Hibernate Child Collection Limited When Using Left Join in Criteria

When using hibernate criteria just altering the join type affects the results of the child collections of the root domain class.

For instance, having class Parent have a one-to-many relationship with class Child with the following data:

Parent 
| id | Name     |
|  1 | Parent 1 |

Child
| id | parent_id | Name   |
|  1 |         1 | Child1 |
|  2 |         1 | Child2 |

Using the following hibernate criteria returns the 1 parent row, and accessing the child collection results in the two rows being returned:

session.createCriteria(Parent.class)
    .createCriteria('child', CriteriaSpecification.INNER_JOIN)
    .add( Restrictions.eq( 'name', 'Child1' ) )
    .list()

However, when changing the above code with a left join, the 1 parent row is returned, but only the matching child row is returned when accessing the child collection.

session.createCriteria(Parent.class)
    .createCriteria('child', CriteriaSpecification.LEFT_JOIN)
    .add( Restrictions.eq( 'name', 'Child1' ) )
    .list()

Why does this side-effect occur? I found a few discussions about using or avoiding this side-effect depending on your intended result, but nothing about why it is there in the first place and whether it was intended. The closest direct question is an old stale defect (http://opensource.atlassian.com/projects/hibernate/browse/HHH-3872).

  • EDIT 3/24: Fixed data *

  • This problem is described here and seems to be fixed in Hibernate 3.6

    https://hibernate.onjira.com//browse/HHH-2049


    I've tried this out: when executing this query and afterwards getting calling parent.getChildren() then:

  • LEFT JOIN: one query is executed containing the parent and the one matching child, no subsequent query is executed when calling getChildren()
  • INNER_JOIN: 2 queries are executed: one to find the parents with matching childs and another when calling getChildren()
  • So it seems that when calling LEFT_JOIN the children (in this case the matching children) are EAGERLY fetched and the children collection of the Parent is already populated. For the INNER_JOIN however this collection is marked as a proxy and is initialized when calling getChildren(); this second query will of course no longer take the restriction on name into account and will simply fetch all children for the Parent.

    This does seem to happen 'inside' hibernate, meaning the join type will affect how hibernate treats the results. Although the generated SQL between a left and inner join differs slightly (in my test the parent.id and child.id were twice in the select clause) the results returned when running the SQL in a DB browser are the same.

    I'm not experienced enough to determine if this a bug or not but it doesn't feel like one.

    链接地址: http://www.djcxy.com/p/6310.html

    上一篇: 创建完美的JPA实体

    下一篇: 在标准中使用左连接时的Hibernate Child Collection Limited