[英]Hibernate N+1 SELECTs with DTO objects
我在使用DTO對象時在進行N + 1選擇的休眠狀態下遇到問題。
例如,此JPQL查詢:
SELECT com.acme.MyDto(t) FROM Thing t
MyDto的構造函數如下所示:
public MyDto(Thing t) {
...
}
結果查詢如下:
SELECT t.id FROM thing t WHERE condition
隨后是每一行的所有單個查詢,即:
SELECT t.id, t.column1, t.column2 FROM thing t WHERE t.id = 1
SELECT t.id, t.column1, t.column2 FROM thing t WHERE t.id = 2
SELECT t.id, t.column1, t.column2 FROM thing t WHERE t.id = 3
...
但是,如果構造函數不接受Entity,而是接受每個單獨的列,則冬眠的行為將與您期望的一樣,即:
public MyDto(Integer id, String column1, String column2) {
...
}
然后,生成的SQL如下所示:
SELECT t.id, t.column1, t.column2 FROM thing t WHERE condition
除了創建占用每一列的DTO構造函數之外,還有沒有一種方法可以讓休眠模式從一開始就一次選擇所有列?
我們正在使用的表在可嵌入對象中分布了100多個列,因此維護一個巨大的構造函數很煩人。 該表已被高度規范化,並且沒有聯接。
第一次讀錯您的問題...我不記得使用DTO來獲取整個實體,而不僅僅是一些特定的列,所以我不確定為什么當您將整個實體用作對象時,Hibernate的行為會如此DTO構造函數中的參數。 無論如何,您可以通過查詢獲取實際Things
來解決此問題,然后在循環中構造DTO,類似於以下內容:
public List<ThingDTO> getThingDTOs( ... )
{
Query query = em().createQuery("FROM Thing t WHERE ...");
query.setParameter( ... );
List<Thing> things = query.getResultList();
List<ThingDTO> thingDTOs = new ArrayList(things.size());
for(Thing t : things)
{
thingDTOs.add(new ThingDTO(t));
}
return thingDTOs
}
這不是很漂亮,但是這種方式Hibernate應該一次性獲取所有需要的行
您可能已經注意到,構造函數表達式方法有很多缺點。 如果您需要嵌套的關聯,它將變得更糟。 這里使用實體對象的主要問題是您仍然可能會遇到N + 1個查詢問題。 不久前,我就該主題寫了一篇博客文章 ,論證了為什么我創建了Blaze-Persistence Entity Views的理由,該視圖允許將DTO映射為接口。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.