延迟 = false 的 Hibernate 二级缓存对象会导致默认的 fetch = join,它是否在任何地方都有记录?
-
21-09-2019 - |
题
我遇到了以下明显未记录的问题,我想了解是否
- 我做错事情了
- 有人遇到同样的问题吗?
- 真的没有任何地方记录吗?或者我错过了什么?
行为是假定以下映射
<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不在缓存中)。
不隶属于 StackOverflow