Hibernate二级缓存对象是lazy = false,导致默认的fetch = join,是否记录在任何地方?

Era*_*dan 6 hibernate hibernate-mapping second-level-cache

我经历了以下明显无证问题,我想了解是否

  1. 我做错事情了
  2. 有没有人遇到同样的问题?
  3. 在任何地方都没有记录吗?还是我错过了什么?

行为是这个假设以下映射

<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>
Run Code Online (Sandbox Code Playgroud)

首先,作为背景,多对一关系上的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>
Run Code Online (Sandbox Code Playgroud)

现在为什么会出现这个问题?而不是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>
Run Code Online (Sandbox Code Playgroud)

答案就是 - 没有任何改变!

显然人们会认为Hibernate足够聪明,无法理解不应该加载这种类型的对象,但是由于默认的fetch从select更改为join,所以Hibernate没有选择(你无法加入真正的表)还有二级缓存)

所以Hibernate做了它所说的,并使用一个连接从数据库中获取一个对象,它已经在二级缓存中

我发现的解决方案是将映射更改为fetch ="select"

现在当Bar的第二个选择即将发布时,Hibernate知道它不应该进入数据库,并从缓存中获取它.只执行一次查询(预热后)

ber*_*ami 4

我遇到了同样的问题,并发现自己将所有将被缓存的多对一关系标记为fetch="select". 当查询建立时,Hibernate无法知道所请求的Bar实例是否在二级缓存中(假设Foo不在缓存中)。