JPA 2.1:不同步的持久性上下文
JPA 2.1版帶來了一種新的方式來處理持久性上下文與當(dāng)前JTA事務(wù)以及資源管理器之間的同步。 術(shù)語資源管理器來自Java事務(wù)處理API ,它表示操縱一個(gè)資源的組件(例如,使用JDBC驅(qū)動程序操縱的具體數(shù)據(jù)庫)。 默認(rèn)情況下,容器管理的持久性上下文的類型為SynchronizationType.SYNCHRONIZED ,即,該持久性上下文自動加入當(dāng)前的JTA事務(wù),并將對持久性上下文的更新傳播到基礎(chǔ)資源管理器。
通過創(chuàng)建新類型為SynchronizationType.UNSYNCHRONIZED的持久性上下文,將禁用事務(wù)的自動連接以及將更新傳播到資源管理器。 為了加入當(dāng)前的JTA事務(wù),代碼必須調(diào)用EntityManager joinTransaction()方法。 這樣,EntityManager的持久性上下文將在事務(wù)中登記,并為后續(xù)通知注冊。 提交或回滾事務(wù)后,持久性上下文將離開事務(wù),并且不會附加到任何其他事務(wù),直到再次為新的JTA事務(wù)調(diào)用joinTransaction()方法joinTransaction() 。
JPA 2.1之前,一個(gè)可以實(shí)現(xiàn)與一個(gè)跨越多個(gè)方法調(diào)用的對話@Stateful由亞當(dāng)邊描述會話Bean 在這里 :
@Stateful @TransactionAttribute(TransactionAttributeType.NEVER) public class Controller {@PersistenceContext(type = PersistenceContextType.EXTENDED)EntityManager entityManager;public Person persist() {Person p = new Person();p.setFirstName("Martin");p.setLastName("Developer");return entityManager.merge(p);}public List<Person> list() {return entityManager.createQuery("from Person", Person.class).getResultList();}@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)public void commit() {}@Removepublic void remove() {} }持久性上下文的類型為EXTENDED ,因此,其生存期比它所附加的JTA事務(wù)的壽命長。 由于持久性上下文默認(rèn)也是SYNCHRONIZED類型,因此它將在調(diào)用任何會話bean方法時(shí)自動加入正在運(yùn)行的任何事務(wù)。 為了防止大多數(shù)Bean方法發(fā)生這種情況,注釋@TransactionAttribute(TransactionAttributeType.NEVER)告訴容器不要為此Bean打開任何事務(wù)。 因此,方法persist()和list()無需事務(wù)即可運(yùn)行。 對于方法commit()此行為是不同的。 這里的注釋@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)告訴容器在調(diào)用該方法之前創(chuàng)建一個(gè)新事務(wù),因此Bean的EntityManager將自動加入該事務(wù)。
使用新的SynchronizationType.UNSYNCHRONIZED類型,可以如以下清單所示重寫上面的代碼:
@Stateful public class Controller {@PersistenceContext(type = PersistenceContextType.EXTENDED,synchronization = SynchronizationType.UNSYNCHRONIZED)EntityManager entityManager;public Person persist() {Person p = new Person();p.setFirstName("Martin");p.setLastName("Developer");return entityManager.merge(p);}public List<Person> list() {return entityManager.createQuery("from Person", Person.class).getResultList();}public void commit() {entityManager.joinTransaction();}@Removepublic void remove() {} }現(xiàn)在,EntityManager不會自動加入當(dāng)前事務(wù),我們可以省略@TransactionAttribute批注。 在我們明確加入之前,任何正在運(yùn)行的事務(wù)都不會對EntityManager產(chǎn)生影響。 現(xiàn)在,這是在commit()方法中完成的,甚至可以基于某些動態(tài)邏輯來完成。
為了測試上面的實(shí)現(xiàn),我們利用了一個(gè)簡單的REST資源:
@Path("rest") @Produces("text/json") @SessionScoped public class RestResource implements Serializable {@Injectprivate Controller controller;@GET@Path("persist")public Person persist(@Context HttpServletRequest request) {return controller.persist();}@GET@Path("list")public List<Person> list() {return controller.list();}@GET@Path("commit")public void commit() {controller.commit();}@PreDestroypublic void preDestroy() {} }該資源提供了持久化人員,列出所有持久化人員并提交當(dāng)前更改的方法。 當(dāng)我們要使用有狀態(tài)會話Bean時(shí),我們用@SessionScoped注釋資源,然后讓容器注入Controller Bean。
在將應(yīng)用程序部署到某個(gè)Java EE容器之后,通過調(diào)用以下URL,一個(gè)新人員將被添加到非同步的持久性上下文中,但不會存儲在數(shù)據(jù)庫中。
http://localhost:8080/jpa2.1-unsychronized-pc/rest/persist即使調(diào)用list()方法也不會返回新添加的人員。 只有最終通過調(diào)用commit()將持久性上下文中的更改與基礎(chǔ)資源同步,才將insert語句發(fā)送到基礎(chǔ)數(shù)據(jù)庫。
結(jié)論
持久性上下文的新UNSYNCHRONIZED模式使我們可以在不止一個(gè)有狀態(tài)會話bean的方法調(diào)用上實(shí)現(xiàn)對話,并且可以靈活地根據(jù)我們的應(yīng)用程序邏輯動態(tài)地加入JTA事務(wù),而無需任何注釋魔術(shù)。
- PS:源代碼可從github獲得 。
翻譯自: https://www.javacodegeeks.com/2015/03/jpa-2-1-unsynchronized-persistence-context.html
總結(jié)
以上是生活随笔為你收集整理的JPA 2.1:不同步的持久性上下文的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浙江省投标(浙江投标备案)
- 下一篇: 服务器安装linux系统安装教程(服务器