Hibernate 雖簡化了資料存取,但不當使用極易導致效能瓶頸。以下針對 Oracle 環境,整理七項經實戰驗證的優化方向。
Oracle JDBC 預設 fetchSize=15,每次只取 15 筆,頻繁網路往返。建議在 Spring 容器中設定 hibernate.jdbc.fetch_size 為 30~100(視記錄大小而定),可顯著減少 Round-trip。超過 100 反而增加記憶體壓力,效能增益遞減。
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>
</props>
</property>
對極少變動的報表、首頁等,生成靜態 HTML,完全繞過 Java 渲染與資料庫查詢,極致提升回應速度。
避免在 HQL/SQL 使用 IN 子查詢、遞迴查詢;將複雜邏輯下推至資料庫 View/Stored Procedure,或拆分為多次簡單查詢在記憶體組裝。代碼品質與架構合理性才是效能基石。
list() / iterate()list():一次性載入所有實體至 Session,記憶體壓力大。iterate():延遲載入,逐筆發 SQL,適合「結果集大但僅使用少數」或「大量重複資料可命中二級快取」場景。一對多、多對一關聯預設 lazy="true",僅在存取集合時觸發 SQL,減少不必要的 Join 與物件建立。但需注意 Session 生命週期,避免 LazyInitializationException。
若 cascade="save-update" 或 "all",新增父實體時若集合已有元素,Hibernate 可能額外執行 UPDATE 關聯表。建議:新增前先 collection.clear(),或改用 cascade="persist"。
開發期開啟 show_sql=true,觀察每頁請求的 SQL 條數,目標控制在 100~150 條以內。批次操作使用 StatelessSession 或 JDBC 批次,定期 session.flush() / clear() 釋放記憶體。
優化無銀彈,關鍵在於「理解 Hibernate 行為」並針對業務場景取捨。定期 Profile、分析 Slow Query Log、配合資料庫索引調整,才能持續保持高效能。