6

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

  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 没有选择(您不能使用二级缓存,但)

所以 Hibernate 做它被告知的事情,并使用一个连接从数据库中获取一个对象,它已经在 2 级缓存中

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

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

4

1 回答 1

4

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

于 2010-01-01T17:35:58.547 回答