前言
Entity Bean 模擬持久業務物件,容器提供優化與服務。Sun 工程師實踐總結七條規則,涵蓋效能、適應性與避坑指南。
一、優先採用容器管理持久化 (CMP)
- 大幅減少編碼工作,容器與產生代碼中存在大量優化可能。
- 容器存取記憶體 Bean 快取,監控變更:未變更時提交前避免寫入資料庫,減少無謂資料庫呼叫。
find 方法優化:依參考搜尋 Entity 後緊接使用時,CMP 可合併「尋找主鍵」與「讀取資料」為單一資料庫存取。
二、撰寫同時支援 CMP 與 BMP 的程式碼架構
部署環境不確定是否支援 CMP,需允許 BMP 部署且不破壞 CMP 優化。
錯誤嘗試:繼承模型導致多重繼承問題
- CMP 超類含業務邏輯,BMP 子類含資料庫存取碼 → 需同時繼承 CMP 超類與 BMP 超類 → Java 不支援多重繼承。
- 難以支援可變持久化實作(不同資料庫廠商/類型)。
正確解法:DAO (Data Access Object) 模式
- 抽象所有 BMP 類共同持久化邏輯為 DAO 輔助類。
- 透過 DAO 介面產生多個 DAO 子類(針對不同 DB),執行時依環境變數/DB 類型實例化適當實作。
- CMP 實作與 DAO 可方便繼承,BMP 類僅含代表性框架碼,易複製修改、甚至工具自動產生。
註:EJB 1.1 規範不允許繼承自 Home 介面的 Entity 類型擴充,阻礙 Factory 方法等設計。
三、在 ejbStore 中最小化資料庫存取
- CMP 時容器自動優化,容器 CMP 優化能力為效能關鍵指標。
- BMP 部署時:快取維護 dirty flag。所有快取變更設定 flag,
ejbStore 檢查 flag,未設定則跳過資料庫寫入。對頻繁查詢少修改的 Bean(如查表)極有效。
- 注意:dirty flag 屬資料庫存取優化,宜在 BMP 碼中設定(DAO 不呼叫業務邏輯,非最佳設定點)。
四、查找與定位一律使用 Reference Cache
- JNDI 查找資料源、Bean 參考、環境實體等資源耗資源。
- 解法:
setEntityContext (Session Bean 用 setSessionContext) 中一次性查找所有參考存為實例變數。此方法僅實例化時呼叫一次,開銷可接受。
- 嚴禁在頻繁呼叫方法(資料庫存取、
ejbLoad、ejbStore)中查找。
- 定位其他 Entity Bean 同理:適當處快取,
ejbActivate 中清除僅對當前實體有效的參考。
五、永遠使用 PreparedStatement (預備 SQL 語句)
- 關聯式資料庫主流,Bean 作者寫資料庫存取碼時必須用 SQL。
- 未預備語句:資料與語句同字串傳遞,資料不匹配導致快取失效。
- 預備語句:無資料語句先傳遞,資料庫編譯快取,後續執行僅傳資料,語句快取命中率近 100%,小型存取可減少 90% 執行時間。
六、嚴格關閉所有 Statement
- 未關閉 Statement 對應資料庫開啟游標,浪費資源。
- 雖 GC 最終會關閉,但時機不可控。必須在
finally 區塊確保關閉,且關閉時捕獲所有例外,避免導致其他 Statement 被忽略或保持開啟。
七、避免死鎖
- 容器決定
ejbStore 調用順序(通常事務結束時),涉及多 Entity Bean/實體時順序未定義,開發者無法控制資料庫記錄鎖定順序 → 易發生死鎖。
- 商用應用伺服器鮮少妥善處理資料庫鎖定,部署者須自行解決。
- 經驗規則:容器按事務中業務方法首次調用順序調用
ejbLoad/ejbStore。例:同一事務中 EB1.m1 先於 EB2.m2 → 假定 EB1.ejbStore 先於 EB2.ejbStore → EB1 相關記錄先鎖定。
- 避免死鎖:**全應用程式確保任何事務中 EB1 總在 EB2 之前被調用**。嚴格處理調用順序可保證在現有伺服器上較好運行。
展望
有效運用七條規則,大幅提升 Bean 效能與適應性,支援不同持久化類型,實現「一次編寫,處處高效運行」。附範例原始碼 Vehicle、Car Bean 示範多數規則,可作為未來開發基礎模板。