我在 Car 和 Engine 之间有一个双向的一对一关联,映射如下:(使用 Hibernate 3.6)
<class name="org.example.Car">
<id column="id" name="PID">
<generator class="uuid2" />
</id>
<version name="Version" column="version" />
<many-to-one cascade="all" name="Engine" not-null="true" unique="true" />
</class>
<class name="org.example.Engine">
<id column="id" name="PID">
<generator class="uuid2" />
</id>
<version name="Version" column="version" />
<one-to-one cascade="all" name="Car" property-ref="Engine" />
</class>
当我执行以下条件查询以加载所有汽车并急切获取它们的引擎时
session().createCriteria(Car.class)
.setFetchMode("Engine", FetchMode.JOIN)
.list();
我得到一个选择来查找所有汽车,然后为找到的每辆汽车选择另一个:
select this_.id ... from Car this_ inner join Engine engine2_ on this_.Engine=engine2_.id
select car0_.id ... from Car car0_ where car0_.engine=?
select car0_.id ... from Car car0_ where car0_.engine=?
select car0_.id ... from Car car0_ where car0_.engine=?
...
Engine
在设置每个加载的属性时,Hibernate 似乎会感到困惑。在TwoPhaseLoad.initializeEntity
中,它尝试解析 Car 属性Engine
并发出另一个选择。
如果使用 createAlias 而不是 setFetchMode,我会得到预期的单选并且一切正常:
session().createCriteria(Car.class)
.createAlias("Engine", "engine")
.list();
我的印象是这两个条件查询应该表现相同。我的映射有什么可以改变的吗?我应该开始使用 createAlias 而不是 setFetchMode 吗?
更新:所以,第二个查询也不好。它实际上加入了 Engine,然后再次加入 Car 以进行反向引用:
select this._id ... from Car this_
inner join Engine engine1_ on this_.engine=engine1_.id
left outer join Car car3_ on engine1_.id=car3_.engine
hibernate 似乎没有意识到它们是同一个关联的两端。从 Engine -> Car 中删除引用修复它,但如果我能在保留引用的同时让它工作,那就太好了。