Hibernate 為非標準 ORM 方案;OpenJPA 實現 JPA 規範(Java EE 5 核心),基於標準 API 編碼可避免供應商鎖定。本文基於 Hibernate 3.0 / EJB 2.1 與 OpenJPA 0.9.7 / EJB 3.0 實戰對比。
| Hibernate (org.hibernate) | JPA (javax.persistence) | 說明 |
|---|---|---|
| Configuration | Persistence | 引導類,創建工廠 |
| SessionFactory | EntityManagerFactory | 線程安全,應用級單例 |
| Session | EntityManager | 線程不安全,請求級,CRUD 核心 |
| Transaction | EntityTransaction | 事務邊界管理 |
| Query | Query | 查詢執行介面 |
// Hibernate
private static SessionFactory sf;
sf = new Configuration().configure("name").buildSessionFactory();
// OpenJPA
private static EntityManagerFactory emf;
emf = Persistence.createEntityManagerFactory("name"); // 查找 META-INF/persistence.xml
// Hibernate
Session s = (Session) tls.get();
if (s == null) { s = getSessionFactory().openSession(); tls.set(s); }
// OpenJPA
EntityManager em = (EntityManager) tls.get();
if (em == null) { em = getEntityManagerFactory().createEntityManager(); tls.set(em); }
// Hibernate
Transaction tx = session.beginTransaction();
tx.commit(); / tx.rollback();
// OpenJPA
EntityTransaction tx = em.getTransaction();
tx.begin();
tx.commit(); / tx.rollback();
OpenJPA 實際無需 ThreadLocal 存儲事務,可直接鏈式調用。
| 操作 | Hibernate | OpenJPA | 注意 |
|---|---|---|---|
| 持久化新對象 | session.save(obj) | em.persist(obj) | |
| 主鍵查詢 | session.load(clz, id) | em.find(clz, id) | find 立即查詢,load 可延遲 |
| 更新分離對象 | session.saveOrUpdate(obj) | em.merge(obj) | merge 返回新托管實例,需接收返回值 |
| 刪除 | session.delete(obj) | em.remove(obj) |
EJB 2.1 實現 SessionBean 介面與回調方法;EJB 3.0 僅需 @Stateless 註解,無需 Home/Component 介面與部署描述符,配置移至註解。業務邏輯結構保持不變,僅底層 API 調用替換。
Hibernate:<discriminator> + <subclass>;OpenJPA:SINGLE_TABLE 策略 + <discriminator-column> + <discriminator-value>。子類無獨立表,屬性提升至基表,非空約束受限。
Hibernate:<joined-subclass> + <key>;OpenJPA:JOINED 策略 + <primary-key-join-column>。子類獨立表,支援非空約束,查詢需連接,最靈活。
Hibernate:<component> 內嵌子對象屬性至父表;OpenJPA:<embedded> + <embeddable> 實體。數據模型同為單表。
Hibernate:子類 <many-to-one> + column;OpenJPA:子實體 <many-to-one> + <join-column>。父實體定義主鍵。
詳見下篇文檔,涉及單向/雙向選擇、擁有端判定、OpenJPA 不支援單向外鍵映射等關鍵差異。