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

Hibernate二级缓存对象为lazy=false,导致默认的fetch=join,是否在任何地方记录?,hibernate,second-level-cache,hibernate-mapping,Hibernate,Second Level Cache,Hibernate Mapping,我遇到了以下明显未记录的问题,我想了解 我做错了什么 有人遇到过同样的问题吗 它真的没有记录在任何地方吗?还是我错过了什么 行为是这样的 假设以下映射 <class name="org.sample.Foo" table="foo"> ... <many-to-one name="bar" class="org.sample.Bar"/> </class> <class name="org.sample.Bar" table="bar"

我遇到了以下明显未记录的问题,我想了解

  • 我做错了什么
  • 有人遇到过同样的问题吗
  • 它真的没有记录在任何地方吗?还是我错过了什么
  • 行为是这样的 假设以下映射

    <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”):

    
    ...
    ...
    
    为什么这会成为一个问题?Hibernate将在一次选择中加载非惰性引用及其“父对象”,而不是2次选择(在一次选择中使用Bar加载Foo)

    这实际上是有道理的,既然对象不是懒惰的,为什么不加载它呢

    答案是:如果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足够聪明,能够理解不应该加载这种类型的对象,但是由于默认的获取已从select更改为join,Hibernate没有选择余地(您还不能使用二级缓存连接实际表)

    因此,Hibernate按照要求执行操作,并使用联接从数据库中获取对象,该对象已经在二级缓存中

    我找到的解决方案是将映射更改为fetch=“select”


    现在,当第二个selectforbar即将运行时,Hibernate知道它不应该进入数据库,并从缓存中获取它。只有一个查询会执行(预热后)

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

    获取行为取决于用于查询对象的API。您使用的是HQL还是Criteria API?都不是一个简单的session.load(Foo.class,id),但它不奇怪吗?它没有被记录,甚至没有在官方的商业书籍中?即使在论坛上或在这里,所以我发现没有提到这个问题…我同意。但是为了理解hibernate到底做了什么,我经常需要进行sql日志记录,看看实际发生了什么。
    <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>