EJB 1.1/2.x 時代,CMP (Container-Managed Persistence) 是 J2EE 規范定義的標準持久化方案。Hibernate 作為開源 ORM 框架崛起,最終通過 JPA (Java Persistence API) 成為標準,重塑了 Java 持久化格局。
| 維度 | CMP Entity Bean (EJB 2.x) | Hibernate / JPA |
|---|---|---|
| 編程模型 | 遠程接口 + 本地接口 + Bean 類 + XML 描述符 | POJO 實體類 + 註解/XML 映射 |
| 依賴容器 | 強依賴 EJB 容器 (WebLogic, WebSphere, JBoss) | 輕量級,可運行於 Servlet 容器、獨立應用、Spring 容器 |
| 查詢語言 | EJB-QL (功能弱、語法受限) | HQL/JPQL (功能豐富、面向對象) |
| 關係映射 | 僅支持基本 1:1, 1:N, N:M,無繼承映射 | 完整支持繼承、組合、嵌入、多態關聯 |
| 延遲加載 | 不支持 (EJB 2.0) / 有限支持 (EJB 2.1) | 全方位支持 (proxy, bytecode enhancement) |
| 緩存機制 | 容器管理,不可控 | 一級緩存 + 二級緩存 + 查詢緩存,高度可配置 |
| 事務管理 | 容器管理 (CMT) / Bean 管理 (BMT) | 聲明式 (@Transactional) / 編程式,靈活 |
| 測試性 | 極差,需容器部署 | 優秀,單元測試無需容器 |
| 部署複雜度 | 高 (ejb-jar.xml, 容器特定描述符) | 低 (persistence.xml + 註解) |
| 性能調優 | 依賴容器實現,黑盒 | 透明,可見 SQL、執行計劃、緩存命中率 |
@Entity
@Table(name = "accounts")
public class Account {
@Id @GeneratedValue
private Long id;
@Column(name = "username", nullable = false, unique = true)
private String username;
@OneToMany(mappedBy = "account", cascade = CascadeType.ALL, orphanRemoval = true)
private List orders = new ArrayList<>();
@Embedded
private Address address; // 嵌入對象
// 業務方法
public void addOrder(Order order) {
orders.add(order);
order.setAccount(this);
}
}
// JPQL 面向對象查詢
List accounts = em.createQuery(
"SELECT a FROM Account a JOIN FETCH a.orders o WHERE a.username LIKE :prefix", Account.class)
.setParameter("prefix", "zhang%")
.getResultList();
// Criteria API 類型安全查詢
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery(Account.class);
Root root = cq.from(Account.class);
cq.select(root).where(cb.like(root.get("username"), "zhang%"));
| 關係類型 | 映射註解 | 特點 |
|---|---|---|
| 單向多對一 | @ManyToOne | 最常用,外鍵在從表 |
| 雙向一對多 | @OneToMany(mappedBy=...) | 由多端維護關係 |
| 多對多 | @ManyToMany + @JoinTable | 中間表可攜帶屬性 |
| 繼承策略 | @Inheritance(SINGLE_TABLE/JOINED/TABLE_PER_CLASS) | 三種策略任選 |
| 嵌入對象 | @Embeddable / @Embedded | 值對象複用,無獨立標識 |
EJB 3.0 專家組 (Gavin King - Hibernate 作者領銜) 吸收 Hibernate 精華,制定 JPA 規范:
1999 EJB 1.0 CMP 1.0 (僅基本映射) 2001 EJB 2.0 CMP 2.0 (本地接口、EJB-QL、關係) 2001 Hibernate 1.0 開源 ORM 革命開始 2003 EJB 2.1 CMP 2.1 (消息驅動、定時器) 2004 Hibernate 3.0 成熟穩定,成為事實標準 2006 EJB 3.0 / JPA 1.0 統一規范,Hibernate 為參考實現 2009 JPA 2.0 Criteria API、映射增強 2013 JPA 2.1 存儲過程、實體圖、CDI 集成 2017 JPA 2.2 Java 8 支持、流式查詢、CDI 更緊密 2020+ Jakarta EE 9+ JPA 3.0+ (namespace jakarta.persistence)
CMP Entity Bean 是 J2EE 早期為解決持久化標準化的嘗試,但過度設計導致複雜度失控。Hibernate 以 POJO、透明持久化、豐富映射贏得社區,最終通過 JPA 成為官方標準。今日新項目無理由使用 CMP,應直接採用 JPA (Hibernate/EclipseLink) + Spring/Spring Boot,享受輕量級、可測試、高性能的現代持久化體驗。