Hibernate第二级缓存对象是lazy = false,导致默认的fetch = join,是否在任何地方记录? [英] Hibernate 2nd level cache objects that are lazy=false, result in a default fetch=join, is it documented anywhere?

查看:150
本文介绍了Hibernate第二级缓存对象是lazy = false,导致默认的fetch = join,是否在任何地方记录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到以下显然没有记录的问题,我想了解是否


  1. 我做了错误的事情

  2. 有没有人遇到同样的问题?

  3. 是否真的没有记录在任何地方?或者我错过了什么?

行为是这个
假设以下映射

 < class name =org.sample.Footable =foo> 
...
<多对一名称=barclass =org.sample.Bar/>
< / class>


< class name =org.sample.Bartable =barlazy =false>
...
< / class>

首先,作为背景,Hibernate对 fetch 属性的默认值多对一的关系应该是 select ,这至少是记录的内容(当我找到它时,我会添加链接)



然而,如果被引用的类是lazy =true,显然这只是真的!

显然上面的映射被翻译成this(因为Bar lazy =false):

 < class name =org.sample.Footable =foo> ; 
...
< / class>


< class name =org.sample.Bartable =barlazy =false>
...
< / class>

现在为什么会这样呢?而不是2个选择,Hibernate将加载非懒惰的引用在一个单一的选择与其父(加载Foo与酒吧在一个选择)

这实际上是有道理的,因为对象不是懒惰的,为什么不加载它?



答案是这样的:如果Bar在二级缓存中会发生什么?

 < class name =org.sample.Footable =foo> 
...
< / class>


< class name =org.sample.Bartable =barlazy =false>
< cache usage =transactional/>
...
< / class>

答案就是 - 没有任何变化!


$ b $显然,人们会假设Hibernate足够聪明,可以理解这种类型的对象不应该被加载,但是由于默认获取从select改为join,所以Hibernate没有选择(你不能加入但是)

所以Hibernate会按照它的要求进行操作,并使用连接从数据库中获取一个对象,它已经位于第二级缓存中二级缓存



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



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

解决方案

我遇到同样的问题,一个关系将被缓存为 fetch =select。在建立查询时,Hibernate无法知道所请求的Bar实例是否在第二级缓存中(假设Foo不在缓存中)。


I experience the following apparently undocumented issue, and I want to understand if

  1. I did something wrong
  2. Did anyone encounter the same issue?
  3. Is it really not documented anywhere? or did I miss something?

The behavior is this Assume the following mapping

<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>

First, as a background, Hibernate default value for the fetch attribute on a many-to-one relation should be "select", this is at least what is documented (I'll add the link here when I find it)

However, this is apparently only true if the referenced class is lazy="true"!

so apparently the above mapping is translated into this (because Bar is 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>

Now why would that be an issue? instead of 2 selects, Hibernate will load the non lazy reference in a single select with its "parent" (load Foo with Bar in a single select)

this actually makes sense, since the object is not lazy, why not load it?

The answer is this: what happens if Bar is in the 2nd level cache?

<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>

And the answer to that is - nothing changes!

Apparently one would assume Hibernate is smart enough to understand that objects of this type should not be loaded, but since the default fetch was changed from select to join, Hibernate doesn't have a choice (you can't join a real table with the 2nd level cache, yet)

so Hibernate does what it is told, and uses a join to fetch an object from the database where it is already in the 2nd level cache

The solution I found is to literally change the mapping to fetch="select"

Now when the second select for Bar is about to go, Hibernate understands it should not go to the database, and fetches it from the cache. and only 1 query will execute (after warmup)

解决方案

I encountered the same issue, and found myself marking all many-to-one relations that will be cached as fetch="select". At the time when the query is built up, Hibernate cannot know whether the requested instance of Bar is in the second level cache or not (assuming that Foo is not in cached).

这篇关于Hibernate第二级缓存对象是lazy = false,导致默认的fetch = join,是否在任何地方记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆