在标准中使用左连接时,Hibernate Child Collection Limited

时间:2011-01-24 20:47:01

标签: hibernate criteria hibernate-criteria

使用hibernate标准时,只需更改连接类型会影响根域类的子集合的结果。

例如,让类Parent与类Child具有一对多的关系,并带有以下数据:

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

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

使用以下hibernate标准返回1父行,访问子集合导致返回两行:

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

但是,当使用左连接更改上述代码时,将返回1父行,但在访问子集时仅返回匹配的子行。

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

为什么会出现这种副作用?我发现了一些关于使用或避免这种副作用的讨论,这取决于你的预期结果,但没有关于为什么它首先存在以及是否有意的。最接近的直接问题是陈旧的陈旧缺陷(http://opensource.atlassian.com/projects/hibernate/browse/HHH-3872)。

  • 编辑3/24:固定数据*

2 个答案:

答案 0 :(得分:1)

这里描述了这个问题,似乎在Hibernate 3.6中已经修复了

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

答案 1 :(得分:0)

我试过这个: 执行此查询时,然后调用parent.getChildren()然后:

  • LEFT JOIN:执行一个包含父项和一个匹配子项的查询,调用getChildren()时不执行后续查询
  • INNER_JOIN:执行2个查询:一个查找具有匹配子项的父项,另一个查询调用getChildren()

所以看来,在调用LEFT_JOIN时,子项(在这种情况下是匹配的子项)被EAGERLY获取,并且已经填充了Parent的子集合。 但是对于INNER_JOIN,此集合被标记为代理并在调用getChildren()时被初始化;第二个查询当然不再考虑名称的限制,只会为父母提取所有子项。

这似乎发生在'内部'hibernate中,这意味着连接类型将影响hibernate如何处理结果。虽然左连接和内连接之间生成的SQL稍有不同(在我的测试中,parent.id和child.id在select子句中是两次),但在DB浏览器中运行SQL时返回的结果是相同的。

我没有足够的经验来确定这是否是一个错误,但它不像是一个。