[英]Hibernate @OneToOne loaded even though is lazy
我正在使用 Spring Boot 2.3、Spring 數據和 Hibernate。
我有以下實體
@Entity
@Getter
@Setter
@EqualsAndHashCode(of = "id")
public class User {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Long id;
private String name;
@OneToOne(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Address address;
@Version
private Long version;
}
@Entity
@Getter
@Setter
@EqualsAndHashCode(of = "id")
public class Address {
@Id
private Long id;
private String fullAddress;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id")
@MapsId
private User user;
@Version
private Long version;
}
執行以下代碼時,將執行與用戶存儲庫相關的任何查詢(對我來說這是預期的行為)。
Address addressFromDb = addressRepository.findAll().get(0);
log.info("" + addressFromDb.getUser().getId());
// select address0_.id as id1_0_, address0_.full_address as full_add2_0_, address0_.version as version3_0_ from address address0_
但是當我執行以下代碼時,會有多個查詢,我不明白為什么。 顯然,從用戶到地址的FetchType.LAZY
不受尊重。
User userFromDb = userRepository.findAll().get(0);
// select user0_.id as id1_4_, user0_.name as name2_4_, user0_.version as version3_4_ from user user0_
// select address0_.id as id1_0_0_, address0_.full_address as full_add2_0_0_, address0_.version as version3_0_0_ from address address0_ where address0_.id=?
我錯過了什么?
為了更有幫助和更清楚,我創建了以下github repo
Hibernate (或更具體地說是PersistenceContext
)需要知道實體是否存在,以便它可以決定是為實體提供代理還是null
。 這不適用於XToMany
關系,因為整個集合可以包裝在代理中,在特殊情況下它將為空。
還需要指出的是, FetchType
只是對 JPa 實現的建議,不能保證在任何情況下都會實現。 您可以在此處閱讀有關@OneToOne
的更多信息,尤其是在獲取策略方面:
雖然可以延遲獲取單向 @OneToOne 關聯,但雙向 @OneToOne 關聯的父端卻不能。 即使指定關聯不是可選的並且我們有 FetchType.LAZY,父端關聯的行為也類似於 FetchType.EAGER 關系。 EAGER fetching 很糟糕。
即使 FK 不是 NULL 並且父端通過可選屬性(例如 @OneToOne(mappedBy = "post", fetch = FetchType.LAZY, optional = false))知道其不可為空性,Hibernate 仍然會生成二級 select 語句。
對於每一個托管實體,Persistence Context 都需要實體類型和標識符,因此在加載父實體時必須知道子標識符,而找到關聯的 post_details 主鍵的唯一方法是執行二級查詢。
字節碼增強是唯一可行的解決方法。 但是,它僅在父端使用 @LazyToOne(LazyToOneOption.NO_PROXY) 注釋並且子端未使用 @MapsId 時才有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.