延迟 = false 的 Hibernate 二级缓存对象会导致默认的 fetch = join,它是否在任何地方都有记录?

StackOverflow https://stackoverflow.com/questions/1968767

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

  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>

首先作为背景,Hibernate默认值为 拿来 多对一关系的属性应该是“选择”,这至少是记录的内容(当我找到它时,我会在此处添加链接)

然而,这显然只有当引用的类是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>

现在为什么这会成为一个问题呢?Hibernate 将在单个选择中加载非惰性引用及其“父级”(而不是 2 个选择)(在单个选择中加载 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 足够聪明,能够理解不应加载这种类型的对象,但由于默认获取已从 select 更改为 join,Hibernate 没有选择(您无法将真实的表与二级缓存,还)

所以 Hibernate 按照它的指示执行操作,并使用连接从数据库中获取已位于二级缓存中的对象

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

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

有帮助吗?

解决方案

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top