Criteria query - setFetchMode vs createAlias,n + 1选择

时间:2012-12-17 19:36:00

标签: hibernate hibernate-mapping criteria-api

我在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中,它会尝试解析Engine上的Car属性并发出另一个选择。

如果使用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并不意识到它们是同一个关联的两端。从引擎中删除引用 - &gt;汽车修理它,但如果我能在保持参考的同时使其工作,那将是很好的。

1 个答案:

答案 0 :(得分:1)

我认为您的问题与hibernate中的错误有关。您可以检查发布的解决方法是否适合您。

Bug Report