我遇到了以下明显未记录的问题,我想了解是否
- 我做错事情了
- 有没有人遇到同样的问题?
- 它真的没有任何地方记录吗?还是我错过了什么?
行为是这样假设以下映射
<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 没有选择(您不能使用二级缓存,但)
所以 Hibernate 做它被告知的事情,并使用一个连接从数据库中获取一个对象,它已经在 2 级缓存中
我找到的解决方案是从字面上将映射更改为 fetch="select"
现在,当 Bar 的第二次选择即将进行时,Hibernate 知道它不应该进入数据库,并从缓存中获取它。并且只会执行 1 个查询(预热后)