在条件中使用 Left Join 时 Hibernate Child Collection 受到限制
当使用休眠标准时,仅更改连接类型就会影响根域类的子集合的结果。
例如,让类 Parent 与类 Child 具有一对多关系,并具有以下数据:
Parent | id | Name | | 1 | Parent 1 | Child | id | parent_id | Name | | 1 | 1 | Child1 | | 2 | 1 | Child2 |
使用以下休眠条件返回 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:固定数据 *
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 *
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这个问题在这里描述,似乎在 Hibernate 3.6
https://hibernate.onjira.com 中得到了修复//浏览/HHH-2049
This problem is described here and seems to be fixed in Hibernate 3.6
https://hibernate.onjira.com//browse/HHH-2049
我已经尝试过这个:
当执行此查询并随后调用parent.getChildren()时,则:
因此,似乎在调用 LEFT_JOIN 时,会急切地获取子级(在本例中为匹配的子级),并且父级的子级集合已经填充。
然而,对于 INNER_JOIN,此集合被标记为代理,并在调用 getChildren() 时初始化;当然,第二个查询将不再考虑名称限制,而只是获取父级的所有子级。
这似乎确实发生在 hibernate“内部”,这意味着连接类型将影响 hibernate 处理结果的方式。尽管左连接和内连接之间生成的 SQL 略有不同(在我的测试中,select 子句中的parent.id 和 child.id 是两次),但在数据库浏览器中运行 SQL 时返回的结果是相同的。
我没有足够的经验来确定这是否是一个错误,但感觉不是一个错误。
I've tried this out:
when executing this query and afterwards getting calling parent.getChildren() then:
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.