Java EE 5 引入 EJB 3.0 與 Java Persistence API (JPA),提供標準化 ORM 解決方案,擺脫 Hibernate 等第三方框架鎖定。本文以 PetStore 應用為例,深入剖析容器內應用設計:分層架構、領域模型、ORM 映射策略、測試方法論與遠端化擴充。
PetStoreService Stateless Session Bean,扮演 Service Facade,將工作委派給 DAO 協作者。AccountDao、OrderDao、ProductDao) 實現為 Stateless Session Bean,注入 EntityManager 執行持久化操作。領域模型 (EJB 3.0 Entity Bean) 於層間傳遞,離開 DAO 層時脫離 (detached),重新進入需 merge 重新關聯。全域運行於同一 JVM,免除分散式部署複雜度。
協作者注入兩種方式:
@EJB(beanName="AccountDao") AccountDao accountDao; // 欄位注入
// 或
@PostConstruct
public void init() { messageSource = new MessageSourceImpl("exceptions"); } // 生命週期回呼
測試策略核心:驗證與協作者的交互,採用 EasyMock 動態 Mock。
@PersistenceContext(unitName="manager1") protected EntityManager em;
// 查詢範例
profile = (UserProfile) em.createQuery(
"from UserProfile up where up.login = :login")
.setParameter("login", login).getSingleResult();
// 持久化
em.persist(account);
此層為持久化感知類別最密集區,需容器內測試策略。
@Id @GeneratedValue(strategy=SEQUENCE, generator="AccountSeq") @Column(name="account_sysid") 對應主鍵。@Version @Column(name="row_version")。預設 Lazy Loading 下,實體在 EntityManager 內 product.getItems().size() > 0,但脫離後 (呈現層) 同樣程式碼回傳 0。無法單純由物件狀態判斷載入狀態,必須建立專案慣例與規約 (如明確標記需預先載入的關聯)。
領域模型業務方法須在任何層均可安全呼叫,故將業務方法數量壓縮至必要最小集,保留 POJO 特性以利 POJT 測試。
| 維度 | 註解 (Metadata) | XML 映射檔 |
|---|---|---|
| 適用專案 | 小型、少表 (<100)、無專職映射角色 | 中大型、專職映射團隊 |
| 優點 | 開發快、程式碼集中 | 關注點分離、降低資源爭用、彈性高 |
| 缺點 | 模型與映射耦合、測試技術分離 | 維護成本高 |
PetStore 採註解節省時間。資料庫遷移 (商用 DB → PostgreSQL) 無需改映射 (雙方支援 Sequence),但主鍵生成策略區域通常需重寫。全面測試覆蓋關聯映射、抓取行為、級聯持久化至關重要,可利用 JPA 容器外模式執行。
測試重點:及早發現抓取類型或級聯類型變更帶來的負面影響。
本地設計 (同 JVM) 優勢多。若需遠端,新增 Remote Facade (Remote Stateless Session Bean):
未解議題 (Proposed Final Draft 階段):
OptimisticLockException 剛納入,暫仍依賴 Provider 專屬例外 (如 Hibernate StaleObjectStateException)。