Hibernate 中 lazy 屬性控制關聯對象的加載策略。正確配置能顯著減少無效查詢,提升效能。本文以實際映射文件為例,解析 lazy="true" 的作用機制與最佳實踐。
<hibernate-mapping>
<class name="com.pojo.Sortp" table="sortp" catalog="shjdc">
<id name="id" type="java.lang.Integer">
<column name="Id" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String">
<column name="Name" length="40" not-null="true" />
</property>
<!-- 關鍵配置:lazy="true" -->
<set name="productses" inverse="true" cascade="all" lazy="true">
<key>
<column name="Sortid" not-null="true" />
</key>
<one-to-many class="com.pojo.Products" />
</set>
</class>
</hibernate-mapping>
| 設置 | 行為 | SQL 執行時機 | 適用場景 |
|---|---|---|---|
| lazy="true" (默認) | 延遲加載:首次訪問集合時發起查詢 | 調用 sortp.getProductses() 時 | 大多數一對多、多對多關聯;不確定是否會用到子表數據 |
| lazy="false" | 立即加載:查詢主表時同時 JOIN 子表 | 執行 from Sortp 時 | 確定每次查主表必須用到子表數據(極少見) |
| lazy="extra" | 極度延遲:size()、contains() 不加載全集合 | 調用 iterator() 時 | 超大集合,僅需統計數量或判斷包含 |
-- lazy="false":無論是否用到 products,均執行
SELECT s.*, p.* FROM sortp s LEFT JOIN products p ON s.Id = p.Sortid;
-- lazy="true":僅查主表
SELECT * FROM sortp;
-- 後續調用 getProductses() 時才執行
SELECT * FROM products WHERE Sortid = ?;
結論: 除非業務100% 確定每次查主表必用子表,否則堅持 lazy="true"。盲目關閉延遲加載會產生大量無用 JOIN,拖慢主表查詢、增加網路傳輸、消耗記憶體。
Hibernate.initialize(proxy) 在 Session 開啟時顯式初始化JOIN FETCH 或 @EntityGraph 批量預加載。<cache usage="read-write"/>,減少重複懶加載查詢。@OneToMany(mappedBy = "sortp", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<Products> productses = new HashSet<>();
// fetch = FetchType.LAZY 對應 lazy="true"
// FetchType.EAGER 對應 lazy="false"