JPA(Java Persistence API,Java持久化API),定義了對象-關係映射(ORM)以及實體物件持久化的標準介面。
JPA是JSR-220(EJB3.0)規範的一部分,在JSR-220中規定實體物件(EntityBean)由JPA進行支援。
所以JPA不局限於EJB3.0,而是作為POJO持久化的標準規範,可以脫離容器獨立運行,開發與測試更加方便。
下面通過一張圖來看一下JPA的基本概念。然後再做簡要分析。
註:不是真正意義的UML圖啊,只是畫著方便就用rose了。
一、EntityManager,EntityManagerFactory,PersistenceContext三者的關係
1、EntityManager和EntityManagerFactory
EntityManager稱為實體管理器,它由EntityManagerFactory所建立。EntityManagerFactory,作為EntityManager的工廠,包含有當前O-R映射的中繼資料資訊,每個EntityManagerFactory,可稱為一個持久化單元(PersistenceUnit),每個持久化單元可認為是一個資料來源的映射(所謂資料來源,可理解為一個資料庫,我們可以在應用伺服器中配置多個資料來源,同時使用不同的PersistenceUnit來映射這些資料來源,從而能夠很方便的實現跨越多個資料庫之間的事務操作。)
2、EntityManager和PersistenceContext
PersistenceContext,稱為持久化上下文,它一般包含有當前事務範圍內的,被管理的實體物件(Entity)的資料。每個EntityManager,都會跟一個PersistenceContext相關聯。PersistenceContext中儲存的是實體物件的資料,而關聯式資料庫中儲存的是記錄。
EntityManager正是維護這種OR映射的中間者,它可以把資料從資料庫中載入到PersistenceContext中,也可以把資料從PersistenceContext中持久化到資料庫。
EntityManager是應用程式操縱持久化資料的介面,EntityManager的介面方法有:
Persist、merge、remove、refresh、flush,
通過這些介面操縱PersistenceContext中的實體物件與資料庫資料之間的同步。
這裡又牽扯到一個實體物件的生命週期的概念
(1)幾種狀態
New–即未有id值,尚未跟persistence context建立關聯的對象
Managed–有id值,已跟persistence context建立了關聯
Detached–有id值,但沒有(或不再)跟persistence context建立關聯
Removed–有id值,而且跟persistence context尚有關聯,但已準備好要從資料庫中把它刪除。
(2)與EntityManager介面的關係
小小結:EntityManager的作用與hibernate session類似。為了能夠在一個請求周期中使用同一個session對象,在hibernate的解決方案中,提出了currentSession的概念,hibernate中的current session,可以跟JTA事務綁定,也可以跟當前線程綁定。在hibernate中,session管理著所有的持久化對象的資料。而在EJB3中,EntityManager管理著PersistenceContext,PersistenceContext正是被管理的持久化對象的集合。
二、EntityManager的管理方式分為兩種:
1、容器管理的EntityManager– 通過PersistenceContext注入EntityManager對象,或通過jndi查詢到EntityManager
定義方式:
@PersistenceContext(name="test")
private EntityManager em;
容器管理的EntityManager ,它所管理的PersistenceContext的生命週期由PersistenceContextType來配置
(1)Transaction-Scoped PersistenceContext – 由容器建立,隨著Transaction而傳播,隨著Transaction的完成而銷毀,對應用程式本身來說,它對persitence context的建立、銷毀一無所知,完全自動和透明。當entity manager的方法被調用的時候,如果在當前JTA事務中還沒有persistence context,那麼將啟動一個新的persistence context,並將它跟當前的JTA事務關聯。
定義方式:
@PersistenceContext(unitName="myunit", type=PersistenceContextType.TRANSACTION)
private EntityManager em;
如:在Java EE環境下,一個JTA事務通常會橫跨多個組件的調用(比如多個EJB組件的方法調用)。這些組件需要能夠在單個事務範圍內訪問到同樣的Persistence Context。為了滿足這種情況的需要,當EntityManager被注入或通過jndi被查詢的時候,它的Persistence Context將會在當前事務範圍內自動傳播,引用到同一個Persistence unit的EntityManager將使用同樣的Persistence Context。這可以避免在不同的組件之間傳遞EntityManager引用。
(2)Extended-Scoped PersistenceContext – 用於Stateful Session Bean,跨越多個Transaction,隨著Stateful Session Bean的銷毀而銷毀,通常,這可以通過調用一個在stateful session bean中被註解定義為@Remove的方法來結束一個stateful session bean的生命週期。
@PersistenceContext(unitName="test", type=PersistenceContextType.EXTENDED)
private EntityManager em;
2、應用管理的EntityManager– 通過PersistenceUnit注入EntityManagerFactory對象
定義方式:
@PersistenceUnit(unitName="test")
private EntityManagerFactory factory;
應用程式自身需要獨立訪問Persistence Context。即每次建立一個EntityManager都會迫使建立一個新的Persistence Context。這些Persistence Context即使在同一個事務範圍內也不會跟其它EntityManager共用。這個建立過程可以由EntityManagerFactory的createEntityManager方法來建立,通過entityManager.close() / isOpen()方法來管理entityManager及其對應的persistence context.。這被稱為應用管理的實體管理器(application-managed entity manager)。
定義方式:
@PersistenceUnit(unitName="test")
private EntityManagerFactory factory;
public void addStudent(String name) {
EntityManager em = factory.createEntityManager();
三、事務實現
EntityManager底層的事務實現可以使用JTA或RESOURCE_LOCAL類型的事務控制策略。
1、JTA和RESOURCE_LOCAL的區別
(1)JTA一般在容器環境中使用,而RESOURCE_LOCAL一般在J2SE的環境下使用。
在J2SE的環境下,由應用程式自身來建立EntityManagerFactory,並由EntityManagerFactory建立EntityManager,通過EntityManager.getTransaction.begin()方法來開啟事務,commit()方法提交事務等等,這種方式就是RESOURCE_LOCAL的基本使用方法。
Persistence.XML配置樣本:
<persistence-unit name="test" transaction-type="JTA">
JTA常在容器環境下使用,也就是使用JTA類型的EntityManager,這樣,EntityManager的調用都是在一個外部的JTA事務環境下進行的,不用手動開啟,提交事務等
Persistence.XML配置樣本:
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
(2)Container-Managed EntityManager必須是JTA類型的EntityManager,而Application-Managed EntityManager則既可以是JTA類型的EntityManager,也可以是RESOURCE_LOCAL類型的EntityManager。
2、JTA事務與普通JDBC事務的區別
(1)JDBC事務,一般由資料庫本身來執行提交或復原操作(單階段提交)。所有資料庫都有自己的交易管理員,管理執行的日誌,這些管理器只能處理其自身的事務,稱為本地事務。
(2)JTA支援多個資料來源,站在更高的角度上,提供一個“交易處理監聽器(TPM)”來管理和協調這些資料來源之間的事務操作,它必須執行兩階段交易認可協議(2PC)。
1)準備階段-TPM向所有RM(資源管理員,即資料庫)確認狀態,是否可以提交或復原。
2)提交階段-TPM確認提交之後,向所有RM發出提交指令或復原指令
TPM本身會維護交易記錄,以保證持久性或災難恢複等。