问题描述
我有两个实体Item
和Data
,以及一个DTO类ItemData
. ItemData
由Item
和Data
组成,并且没有JPA映射.要检索已填充的ItemData的列表,我在JPQL中使用了构造函数表达式:
I have two entities, Item
and Data
, and a DTO class ItemData
. ItemData
consists of Item
and Data
and has no JPA mapping. To retreive a list of populated ItemDatas, I use a constructor expression in JPQL:
select new my.package.ItemData(i, d)
from Item i, Data d
where i.id = d.itemId
这就是Hibernate正在做的事情:它不是先获取Item
和Data
的数据,而是先获取其ID,然后再在 n 单独的select语句中获取数据.有办法改变这种行为吗?
This is what Hibernate is doing: Instead of fetching both the data of Item
and Data
, it gets their IDs first and the data afterwards in n separate select statements. Is there a way to change this behaviour?
Hibernate:
select
item0_.id as col_0_0_,
data1_.id as col_1_0_
from
ITEM item0_,
DATA data1_
Hibernate:
select
item0_.no as no1_0_,
item0_.description as description1_0_,
item0_.organic as bio1_0_,
item0_.gluten as gluten1_0_,
item0_.laktose as laktose1_0_
from
ITEM item0_
where
item0_.id=?
Hibernate:
select
data0_.amount as amount1_3_0_,
data0_.avg as avg3_0_,
data0_.total as total3_0_
from
DATA data0_
where
data0_.id=?
Hibernate:
select
item0_.no as no1_0_,
item0_.description as description1_0_,
item0_.organic as bio1_0_,
item0_.gluten as gluten1_0_,
item0_.laktose as laktose1_0_
from
ITEM item0_
where
item0_.id=?
Hibernate:
select
data0_.amount as amount1_3_0_,
data0_.avg as avg3_0_,
data0_.total as total3_0_
from
DATA data0_
where
data0_.id=?
...and so on...
推荐答案
使用左联接提取怎么办?
我承认我没有使用CTOR表达式,但是当我需要获取父实体及其子实体时,我使用了左连接获取,它始终像一种魅力一样工作.
我只能假设由于我们在这里处理对象的构造,因此
Hibernate不会想要"将对象部分构造"(或者说,对象处于惰性评估状态"),并且由于您没有使用"left join fetch"执行"eager fetch",因此它执行N +1次获取:
首先,它获取所有ID,然后针对每个相关ID执行另一次获取.
在此处了解更多有关左联接的信息在页面上查找左连接获取")
What about using left join fetch?
I admit I didn't use CTOR expressions, but when I need to fetch a parent entity and its children, I used left join fetch and it always worked like a charm.
I can only assume that since we're dealing here with construction of objects,
Hibernate does not "want" to leave an object "partially constructed" (or let's say - an object in "lazy evaluation state") , and since you did not perform an "eager fetch" using "left join fetch", it performs N+1 fetches:
At first it fetches all the IDs, and then for each relevant ID it performs another fetch.
Read more about left join fetch here (simply look for "left join fetch" at the page)
这篇关于防止"n + 1选择"与JPA/休眠构造函数表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!