我遇到以下明显无证问题,我想了解是否
行为就是这样 假设以下映射
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar"/>
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
首先,作为背景,多对一关系上 fetch 属性的Hibernate默认值应为“ select ”,这至少是什么记录(当我找到它时,我会在这里添加链接)
但是,如果引用的类是lazy =“true”,这显然是正确的!
所以显然上面的映射被翻译成了这个(因为Bar是lazy =“false”):
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
现在为什么会出现这个问题?而不是2个选择,Hibernate将使用其“父”在单个选择中加载非延迟引用(在单个选择中加载Foo和Bar)
这实际上是有道理的,因为对象不是懒惰的,为什么不加载呢?
答案是:如果Bar在二级缓存中会发生什么?
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
<cache usage="transactional" />
...
</class>
答案就是 - 没有任何改变!
显然人们会认为Hibernate足够聪明,不应该加载这种类型的对象,但是由于默认的fetch从select更改为join,所以Hibernate没有选择(你不能加入一个真实的具有二级缓存的表,但是)
所以Hibernate做了它所说的,并使用一个连接从数据库中获取一个已经在二级缓存中的对象
我发现的解决方案是将映射更改为fetch =“select”
现在,当Bar的第二个选择即将发布时,Hibernate知道它不应该进入数据库,并从缓存中获取它。只执行一次查询(预热后)
答案 0 :(得分:4)
我遇到了同样的问题,并发现自己将所有多对一关系标记为fetch="select"
缓存。在构建查询时,Hibernate无法知道所请求的Bar实例是否在二级缓存中(假设Foo未缓存)。