一尘不染

惰性= false的Hibernate 2级缓存对象会导致默认的fetch = join,它在任何地方都有记录吗?

hibernate

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

  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>

首先,作为背景,多对一关系中 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将通过其“父代”在单个选择中加载非延迟引用(在单个选择中使用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没有选择的余地(您无法使用2级缓存,但)

因此,Hibernate会按照所告知的方式进行操作,并使用联接从已经在第二级缓存中的数据库中获取对象

我发现的解决方案是从字面上将映射更改为fetch =“ select”

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


阅读 230

收藏
2020-06-20

共1个答案

一尘不染

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

2020-06-20