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

时间:2009-12-28 10:02:21

标签: hibernate second-level-cache hibernate-mapping

我遇到以下明显无证问题,我想了解是否

  1. 我做错了什么
  2. 有没有人遇到同样的问题?
  3. 在任何地方都没有记录吗?还是我错过了什么?
  4. 行为就是这样 假设以下映射

    <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知道它不应该进入数据库,并从缓存中获取它。只执行一次查询(预热后)

1 个答案:

答案 0 :(得分:4)

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