我遇到以下明显未记录的问题,我想了解是否
行为是这样假定以下映射
<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没有选择的余地(您无法使用2级缓存,但)
因此,Hibernate会按照所告知的方式进行操作,并使用联接从已经在第二级缓存中的数据库中获取对象
我发现的解决方案是从字面上将映射更改为fetch =“ select”
现在,当Bar的第二个选择即将执行时,Hibernate知道它不应该进入数据库,并从缓存中获取它。并且仅执行1个查询(预热后)
我遇到了同样的问题,发现自己将所有多对一关系标记为,并将其缓存为fetch="select"。在建立查询时,Hibernate无法知道所请求的Bar实例是否在二级缓存中(假定Foo不在缓存中)。
fetch="select"