4

使用休眠条件时,仅更改连接类型会影响根域类的子集合的结果。

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

家长
| 编号 | 姓名 |
| 1 | 家长 1 |

孩子
| 编号 | parent_id | 姓名 |
| 1 | 1 | 孩子1 |
| 2 | 1 | 孩子2 |

使用以下休眠条件返回 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:固定数据 *
4

2 回答 2

1

此问题在此处进行了描述,似乎已在 Hibernate 3.6 中修复

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

于 2011-07-11T12:13:20.477 回答
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 子句中出现了两次),但在数据库浏览器中运行 SQL 时返回的结果是相同的。

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

于 2011-03-22T12:43:13.923 回答