簡體   English   中英

Hibernate OneToOne 自動連接抓取(解決n+1問題)

[英]Hibernate OneToOne automatic join fetching (resolving n+1 problem)

Hibernate 3.3 有一個 n+1 select 問題。

為簡單起見,我將只做一個簡短的抽象示例。

假設我們有以下簡單的類:

class MainEntity {
  @Id
  public Long id; //we have a table generator create this id

  @OneToOne ( mappedBy ="main" )
  public SubEntity subEntity;
}

class SubEntity {
 @Id
 @Column( name = "mainId" ) //note that this is the same column as the join column below
 public Long mainId; //in order to have the exact same id as the corresponding MainEntity

 @OneToOne ( fetch = FetchType.LAZY )
 @JoinColumn ( name = "mainId", insertable = false, updatable = false, nullable = false )
 public MainEntity main; //this is used for navigation and queries (" ... subentity.main = :x")
}

如您所見, SubEntityMainEntity的關系由兩個屬性表示,其中mainId屬性是負責管理關系/外鍵的屬性。

這工作得很好,完全符合我們的需求。

但是,急切地加載SubEntityMainEntity存在一個問題。

假設我有一個返回MainEntity集合的查詢。 使用當前設置, Hibernate 將發出 n + 1 個選擇:查詢本身 + n 為每個SubEntity選擇。

當然,我可以在查詢中添加join fetch ,但我更希望 Hibernate 自動執行此操作。 因此我嘗試添加@Fetch( FetchMode.JOIN ) ,但這並沒有做任何事情。

使用@Fetch( FetchMode.SUBSELECT )也沒有問題,這應該將 select 語句減少到 2 - 原始查詢和子實體的 select (至少這是在另一個用@CollectionOfElements@Fetch( FetchMode.SUBSELECT )注釋的屬性上發生的情況@Fetch( FetchMode.SUBSELECT ) )。


join fetch or use a single select in order to eagerly load the sub entities?所以問題是:我如何告訴 Hibernate加入 fetch 或使用單個 select 以便急切地加載子實體? 我錯過了什么嗎?

提前致謝,

托馬斯

PS:可能有問題的一件事可能是mappedBy = "main"沒有引用實際的 id 列,但我無法將其更改為mappedBy = "id"

如果要在 MainEntity 和 SubEntity 之間共享主鍵,請使用PrimaryKeyJoinColumnMapsId注釋。

通過使用PrimaryKeyJoinColumn ,通過使用相同的主鍵將MainEntity表與SubEntity表連接來加載實體。 它應該可以解決 n+1 個問題。

MapsId注釋要求 Hibernate 從另一個關聯實體復制標識符,在我們的示例中,會將SubEntity.mainEntity.id復制到SubEntity.id

@Entity
public class MainEntity {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "main_Id")
    private Long id;

    @OneToOne(cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    private SubEntity  subEntity ;
}


@Entity
public class SubEntity 
{
    @Id @Column(name="main_Id_FK") Long id;

    @MapsId 
    @OneToOne
    @JoinColumn(name = "main_Id_FK")    
    @PrimaryKeyJoinColumn
    private MainEntity mainEntity;        

}

Hibernate 參考文檔:

PrimaryKeyJoinColumn
MapsId

有三個選項可以避免問題 n +1:

 Lot size

 subselect

 Make a LEFT JOIN in the query

這里常見問題1這里常見問題2

暫無
暫無

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

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