2.1 獲取選項
Hibernate 的開發人員很早就知道加載子實體的問題。所以他們做的第一件事就是在註釋中添加一個特殊的提取@OneToMany
參數,@ManyToMany
。
該參數可以取兩個值:
- 渴望的
- 懶惰的
例子:
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
如果fetch 參數等於 EAGER,那麼當加載父實體時,它的所有子實體也將被加載。此外,Hibernate 將嘗試在一個 SQL 查詢中執行此操作,生成大量查詢並一次獲取所有數據。
如果fetch 參數取值為 LAZY,那麼在加載父實體時,不會加載子實體。相反,將創建一個代理對象。
借助這個代理對象,Hibernate 會跟踪對這個子實體的訪問,並在第一次訪問時將其加載到內存中。
如果我們回顧我們的情況並發表評論:
@Entity @Table(name="user")
class User {
@Column(name="id")
public Integer id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "user_id")
public List<Comment> comments;
}
然後你有一個“別緻的選擇”:
如果fetch = FetchType.EAGER
,那麼 Hibernate 將在第一行代碼加載所有註釋:
User user = session.get(User.class, 1); //load all comments here
List<Comment> comments = user.getComments();
如果fetch = FetchType.LAZY
,那麼 Hibernate 將在第 2 行代碼加載所有註釋:
User user = session.get(User.class, 1);
List<Comment> comments = user.getComments(); //load all comments here
正如您已經猜到的那樣,當它沒有加載所有評論時,您沒有選擇 :)
2.2 默認值
如果您沒有為@ManyTo
... 註釋指定提取選項,那麼 Hibernate 將使用默認值。
對於不同的註釋類型,它們略有不同。對於註解@OneToOne
是@ManyToOne
EAGER,對於註解@OneToMany
是@ManyToMany
LAZY。很容易記住——如果我們引用一個對象,那麼它將被完全加載。如果我們引用一個集合,那麼它將在第一次訪問時加載。
2.3 @LazyCollection註解
正如您已經看到的,fetch 參數在處理集合時沒有多大幫助。Hibernate 的創建者試圖通過添加一個特殊的註解來解決這個問題@LazyCollection
。通常是這樣寫的:
@LazyCollection(LazyCollectionOption.TRUE)
映射集合字段時需要指定:
@Entity @Table(name="user")
class User {
@Column(name="id")
public Integer id;
@OneToMany(cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.TRUE)
public List<Comment> comments;
}
此註解有一個值參數,可以採用以下三個值之一:
- 惰性集合選項。真的
- 惰性集合選項。錯誤的
- 惰性集合選項。額外的
前兩個選項與 fetch 選項非常相似。
如果參數設置為LazyCollectionOption.TRUE
,則表示在加載父User對象時,不會從數據庫中加載comments字段的值。Comment 類型的對象將在第一次訪問 comments 字段時加載。其實這個相當於參數FetchType.LAZY
如果參數設置為LazyCollectionOption.FALSE
,則表示comments字段的值會在加載父User對象時從數據庫中加載。Comment 類型的對象將在第一次訪問 comments 字段時加載。事實上,這相當於FetchType.EAGER
.
GO TO FULL VERSION