簡體   English   中英

Hibernate DTO Projections N+1 查詢

[英]Hibernate DTO Projections N+1 queries

剛剛在使用 Hibernate 和 Spring 數據 JPA 時實驗了一個有趣的事實。 我有以下設置 DTO 和實體:

@Getter
@Setter
public class ClassDto {
     private String id;
     private String name;

      public ClassDto(Entity e) {
         this.id = e.id;
        this.name = e.name;
      }

      public ClassDto(String id, String name) {
          this.id = id;
          this.name = name;
      }
}

@Entity
@Setter
@Getter
public class Entity {
     @Id String id;
     String name;
}

為什么這個查詢被執行了 N+1 次。

select new org.xyz.ClassDto(e) from Entity e

雖然這個實體只解構了一次

select new org.xyz.ClassDto(e.id, e.name) from Entity e

我只想要一個關於地下事物如何運作的合乎邏輯的解釋。

謝謝

我猜你正在使用這樣的查詢:

select new org.xyz.ClassDto(e.toManyAssociation) from Entity e

In this case, Hibernate will pass in a proxy instead of a fully initialized entity, so when you access the data of that object in the constructor, Hibernate will lazy load the object. 您可以通過加入關聯並改為傳遞加入別名來解決此問題。

我想你可能對Blaze-Persistence Entity Views感興趣。

我創建了該庫,以允許在 JPA 模型和自定義接口或抽象 class 定義的模型之間輕松映射,例如 Spring Data Projections on steroids。 這個想法是您以您喜歡的方式定義您的目標結構(域模型),並通過 JPQL 表達式將 map 屬性(吸氣劑)定義為實體 model。

使用 Blaze-Persistence Entity-Views 的 DTO model 可能如下所示:

@EntityView(Entity.class)
public interface ClassDto {
    @IdMapping
    Long getId();
    String getName();
}

查詢是將實體視圖應用於查詢的問題,最簡單的就是通過 id 進行查詢。

ClassDto a = entityViewManager.find(entityManager, ClassDto.class, id);

Spring 數據集成允許您幾乎像 Spring 數據投影一樣使用它: https://persistence.blazebit.com/documentation/entity-view/manual-html/。

Page<ClassDto> findAll(Pageable pageable);

最好的部分是,它只會獲取實際需要的 state!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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