簡體   English   中英

使用DTO對象休眠N + 1 SELECT

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM