[英]Prevent “n+1 selects” with JPA/Hibernate constructor expression?
我有兩個實體, 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 個單獨的 select 語句中獲取數據。 有沒有辦法改變這種行為?
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 表達式,但是當我需要獲取父實體及其子實體時,我使用了 left join fetch 並且它總是像魅力一樣工作。
我只能假設既然我們在這里處理對象的構造,
Hibernate 不“想要”留下“部分構造”的對象(或者比方說 - 處於“延遲評估狀態”的對象),並且由於您沒有使用“左連接提取”執行“急切提取”,因此它執行 N +1 獲取:
首先它獲取所有的 ID,然后對每個相關的 ID 執行另一個獲取。
在此處閱讀有關左連接提取的更多信息(只需在頁面上查找“左連接提取”即可)
這是Blaze-Persistence Entity Views的完美用例。
我創建了該庫以允許在 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;
...
}
使用 Blaze-Persistence Entity-Views 的用例的 DTO 模型可能如下所示:
@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 Data 集成允許您像使用 Spring Data Projections 一樣使用它: https : //persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.