我有两个实体,Item
和Data
,以及一个DTO类ItemData
。 ItemData
由Item
和Data
组成,没有 JPA 映射。为了检索填充的 ItemData 列表,我在 JPQL 中使用了一个构造函数表达式:
select new my.package.ItemData(i, d)
from Item i, Data d
where i.id = d.itemId
这就是Hibernate正在做的事情:它不是同时获取Item
和Data
的数据,而是首先获取它们的ID,然后在n个单独的选择语句中获取数据。有没有办法改变这种行为?
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并不"想要"让对象"部分构造"(或者说 - 一个处于"惰性求值状态"的对象),并且由于您没有使用"左连接获取"执行"预先获取",因此它执行N + 1次获取:
首先,它获取所有 ID,然后为每个相关 ID 执行另一个提取。
在此处阅读有关左联接提取的更多信息(只需在页面上查找"左联接提取")
这是 Blaze-Persistence 实体视图的完美用例。
我创建了该库,以允许JPA模型与自定义接口或抽象类定义的模型之间的轻松映射,类似于类固醇上的Spring Data Projections。这个想法是你按照你喜欢的方式定义你的目标结构(域模型),并通过JPQL表达式将属性(getter)映射到实体模型。
我想你的实体模型看起来像这样?
@Entity
class Item {
@Id Long id;
String description;
@OneToMany(mappedBy = "item")
Data data;
...
}
@Entity
class Data {
@Id Long id;
@ManyToOne Item item;
Long amount;
BigDecimal avg;
...
}
您的用例的 DTO 模型可能如下所示,其中包含 Blaze-Persistence 实体视图:
@EntityView(Item.class)
public interface ItemData {
@IdMapping
Long getNo();
String getDescription();
@Mapping("SUM(data.amount)")
Long getAmount();
}
查询是将实体视图应用于查询的问题,最简单的只是按 id 进行查询。
ItemData a = entityViewManager.find(entityManager, ItemData.class, id);
集成允许您像 Spring 数据投影一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features