日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

entitymanager_实体管理器的类型:应用程序管理的EntityManager

發(fā)布時(shí)間:2023/12/3 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 entitymanager_实体管理器的类型:应用程序管理的EntityManager 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

entitymanager

JPA規(guī)范定義了幾種類型的EntityManagers / Persistence Context。 我們可以有:

  • 擴(kuò)展和事務(wù)范圍的EntityManager,
  • 容器管理或應(yīng)用程序管理的EntityManager。
  • JTA或本地資源EntityManager,

除了上述區(qū)別之外,我們還可以在其中存在EntityManager / Persistence Context的兩個(gè)主要上下文– Java EE和Java SE 。 并非每個(gè)選項(xiàng)都適用于Java EE,并且并非每個(gè)選項(xiàng)都適用于Java SE。 在本文的其余部分中, 我將介紹Java EE環(huán)境 。

好的,因此在繼續(xù)本文之前的主題之前(這是使用EntityManagerFactory手動(dòng)創(chuàng)建的Java EE中EntityManager的行為),我們僅簡要介紹一下上述EM類型。

擴(kuò)展與事務(wù)范圍

此功能告訴我們EntityManager的操作是否可能跨越多個(gè)事務(wù)。 默認(rèn)情況下,使用事務(wù)性持久性上下文,這意味著當(dāng)提交當(dāng)前事務(wù)時(shí),將清除所有更改,并分離所有受管實(shí)體。 擴(kuò)展范圍僅適用于有狀態(tài)EJB。 這非常有意義,因?yàn)镾FSB可以保存狀態(tài),因此不必終止一種業(yè)務(wù)方法就意味著結(jié)束事務(wù)。 使用SLSB的情況就不同了–我們有業(yè)務(wù)方法必須在業(yè)務(wù)方法完成時(shí)結(jié)束,因?yàn)樵谙乱淮握{(diào)用中,我們不知道我們將以哪個(gè)EJB實(shí)例結(jié)束。 SLSB僅允許使用事務(wù)范圍的EntityManager。 您可以控制在EntityManager注入期間EntityManager是擴(kuò)展的還是事務(wù)的:

@PersistenceContext(type=javax.persistence.PersistenceContextType.EXTENDED) EntityManager em;

默認(rèn)情況下為javax.persistence.PersistenceContextType.TRANSACTION 。 附帶說明–使用擴(kuò)展的EntityManager可能使您可以創(chuàng)建一些有趣的解決方案; 看看具有事務(wù)性保存方法技巧的 Adam Bien的無事務(wù)bean 。 他使用這種方法使事務(wù)開始和結(jié)束時(shí)自動(dòng)清除所有更改(并且他實(shí)際上通過調(diào)用特殊的人工方法來做到這一點(diǎn)。)僅在容器管理的EntityManagers的情況下才允許擴(kuò)展和事務(wù)范圍的PersistenceContext。

容器管理與應(yīng)用程序管理

在大多數(shù)Java EE應(yīng)用程序中,您只是使用@PersistenceContext注入EntityManager,如下所示:

@PersistenceContext EntityManager em;

實(shí)際上,這意味著您要讓容器為您的EntityManager注入 (容器是在后臺(tái)從EntityManagerFactory創(chuàng)建的。)這意味著EntityManager是由容器管理的。 另外,您可以從EntityManagerFactory自己創(chuàng)建EntityManager。 您可以通過注入獲得它:

@PersistenceUnit EntityManagerFactory emf;

然后,要獲取EntityManager,您需要調(diào)用emf.createEntityManager() 。 這就是–您現(xiàn)在正在使用應(yīng)用程序管理的EntityManager 。 應(yīng)用程序(您)負(fù)責(zé)創(chuàng)建和刪除EntityManager。 每個(gè)應(yīng)用程序管理的持久性上下文都有擴(kuò)展的范圍。

如果要控制已創(chuàng)建的EM,則可以使用-例如,如果要為基礎(chǔ)JPA實(shí)現(xiàn)程序設(shè)置一些屬性,或者只是在業(yè)務(wù)方法將其投入使用之前插入自己。 但是,您將需要跨事務(wù)涉及的多個(gè)bean移動(dòng)創(chuàng)建的EntityManager –容器不會(huì)為您這樣做,并且每次調(diào)用emf.createEntityManager()您都在創(chuàng)建一個(gè)與新PersistenceContext連接的EntityManager。 。 您可以使用CDI進(jìn)行EntityManager的共享,但這是最后一節(jié)之一的主題。

JTA與本地資源

此屬性定義您是要JTA管理EntityManager的事務(wù),還是要使用其直接API開始和提交。 如果您使用的是容器管理的EntityManager,則自動(dòng)意味著您必須使用JTA EntityManager 。 如果您使用的是應(yīng)用程序管理的EntityManager,則可以使用JTA或本地資源。 在現(xiàn)實(shí)生活中,這意味著,如果您使用的是JTA EntityManager,則您只需照顧更高級(jí)別的事務(wù)管理:

  • 聲明性地 使用注釋或XML JTA交易屬性,或
  • 以編程方式 使用javax.transaction.UserTransaction 。

如果您使用的是本地資源EntityManager,則需要更深入一點(diǎn),并使用EntityManager.getTransaction()返回javax.persistence.EntityTransaction并調(diào)用commit(-) , begin(-) , rollback()等。使用transaction-type屬性在persistence.xml定義此功能:

<?xml version='1.0' encoding='UTF-8'?> <persistence ...><persistence-unit transaction-type='RESOURCE_LOCAL' ... > </persistence>

另一個(gè)可能的值(當(dāng)未定義transaction-type時(shí)為默認(rèn)值)是JTA 。

Java EE中由應(yīng)用程序管理的JTA EntityManager

盡管此字幕聽起來很復(fù)雜,但了解EntityManager和PersistenceContexts的所有先前類型后,您應(yīng)該確切了解if指的是什么。

  • “應(yīng)用程序托管”意味著我們將注入@PersistenceUnit EntityManagerFactory而不是EntityManager,
  • 之所以稱為 “ Java EE”,是因?yàn)檫@些示例(在github上發(fā)布)僅在Java EE Application Server中使用 ,
  • “ JTA”,因?yàn)槲覀儗⑹褂肑TA事務(wù)級(jí)別,因此不會(huì)使用javax.persistence.EntityTransaction 。

現(xiàn)在,您需要了解的第一件事是如何使用JTA事務(wù)。 JTA事務(wù)管理有兩種類型-容器(CMT)和Bean管理(BMT)。 容器管理的JTA事務(wù) ( CMT )意味著您使用javax.ejb.TransactionAttribute定義tx是否應(yīng)處于活動(dòng)狀態(tài)以及事務(wù)邊界在何處。 這是默認(rèn)的JTA管理類型。 或者,您可以選擇自己劃定JTA事務(wù)的邊界。 這稱為Bean管理的JTA事務(wù) ( BMT )。應(yīng)用程序(您)負(fù)責(zé)啟動(dòng),回滾或提交事務(wù)。 您如何控制JTA交易? 您可以使用javax.transaction.UserTransaction做到這一點(diǎn)。

您如何獲得一個(gè)? 好吧,至少有3種方法可以做到這一點(diǎn):

  • 它綁定到組件私有名稱空間( java:comp/UserTransaction )中的JNDI,因此您可以使用InitialContext或SessionContext對(duì)其進(jìn)行查找,
  • 您可以使用SessionContext進(jìn)行訪問– SessionContext#getUserTransaction() ,
  • 因?yàn)樗壎ㄔ诒娝苤腏NDI名稱中,所以可以讓容器使用以下方式注入它: @Resource UserTransaction utx; 。

如果您有UserTransaction ,則可以開始劃分事務(wù)中要執(zhí)行的內(nèi)容。 請(qǐng)注意,您仍在控制JTA事務(wù) –您甚至都沒有接觸EntityManager的資源本地事務(wù)。

EntityManager何時(shí)在JTA事務(wù)中?

如果沒有前面的介紹,您可能會(huì)認(rèn)為由應(yīng)用程序管理的EntityManager意味著您將獨(dú)自承擔(dān)一切–創(chuàng)建,共享EntityManager,開始tx,提交,關(guān)閉。 但是,了解了以上所有差異后,您知道可以在應(yīng)用程序管理的EntityManager中使用JTA事務(wù) 。 但是問題是–如何使它知道活動(dòng)的JTA事務(wù)? 如果我們有一個(gè)容器管理的EntityManager,我們知道容器將全部管理它,但是如果我們是一個(gè)人,我們該怎么做? 實(shí)際上, 這取決于我們在哪里創(chuàng)建EntityManager 。 在下面找到一些示例(完整的代碼可以在我的github帳戶上找到:

情況1:我們在沒有活動(dòng)交易的情況下調(diào)用以下代碼(因此,對(duì)于CMT,我們具有TransactionAttribute.NEVER或TransactionAttribute.NOT_SUPPORTED ;對(duì)于BMT,我們不調(diào)用UserTransaction.begin() :

EntityManager em = emf.createEntityManager(); em.persist(new Customer(firstName, lastName));

結(jié)果: EntityManager操作在持久化時(shí)不會(huì)引發(fā)任何異常,但是所有更改都不會(huì)提交 。 沒有活動(dòng)的事務(wù),因此不會(huì)進(jìn)行任何更改。

情況2:我們使用BMT調(diào)用以下代碼:

utx.begin();EntityManager em = emf.createEntityManager();em.persist(new Customer(firstName, lastName));utx.commit();

結(jié)果:在JTA提交期間,新數(shù)據(jù)已正確保留(在最后一行。)

情況3:我們使用BMT調(diào)用以下代碼:

EntityManager em = emf.createEntityManager(); utx.begin();em.persist(new Customer(firstName, lastName));utx.commit();

結(jié)果: EntityManager在事務(wù)之外,因?yàn)樗窃趩?dòng)JTA事務(wù)之前創(chuàng)建的。 盡管已提交JTA事務(wù),但更改不會(huì)持久保存。 沒有異常被拋出。

在第二個(gè)示例的情況下,您可能會(huì)問自己-是否可以首先創(chuàng)建EntityManager,然后開始事務(wù),最后以某種方式使EntityManager知道周圍的TX? 如果事實(shí)是這樣,則可以執(zhí)行此操作,而這正是EntityManager#joinTransaction()方法的用途。 以下兩種情況將向您展示如何使用它:

情況4:我們使用BMT調(diào)用以下代碼:

EntityManager em = emf.createEntityManager(); utx.begin(); em.joinTransaction();em.persist(new Customer(firstName, lastName));utx.commit();

結(jié)果:在這里,我們明確地告訴EntityManager加入活動(dòng)的JTA事務(wù)。 結(jié)果, EntityManager將在JTA commit期間刷新其所有更改 。

情況5:我們使用BMT調(diào)用以下代碼:

EntityManager em = emf.createEntityManager(); utx.begin();em.joinTransaction();em.persist(new Customer(firstName, lastName));utx.commit();utx.begin();em.joinTransaction();em.persist(new Customer(firstName, lastName));utx.commit();

結(jié)果: 兩種EntityManager操作均正確存在。 在這里,我們證明了應(yīng)用程序管理的持久性上下文可以跨越多個(gè)JTA事務(wù) (請(qǐng)注意,我們沒有創(chuàng)建另一個(gè)EntityManager,而只是重用了先前事務(wù)中使用的那個(gè))。在這里,您可以看到JPA規(guī)范(JPA規(guī)范) 2.0最終版本)告訴您有關(guān)應(yīng)用程序管理的持久性上下文的信息:

7.7應(yīng)用程序管理的持久性上下文

使用JTA應(yīng)用程序管理的實(shí)體管理器時(shí),如果在當(dāng)前JTA事務(wù)的范圍之外創(chuàng)建實(shí)體管理器,則應(yīng)用程序有責(zé)任通過調(diào)用EntityManager.joinTransaction將實(shí)體管理器與事務(wù)關(guān)聯(lián)(如果需要)。 。 如果實(shí)體管理器是在JTA事務(wù)范圍之外創(chuàng)建的,則除非調(diào)用EntityManager.joinTransaction,否則它不與事務(wù)關(guān)聯(lián)。
使用CDI共享EntityManager

如前所述,如果要在組成一個(gè)事務(wù)的組件之間共享EntityManager,則應(yīng)手動(dòng)傳遞它(畢竟,它是“應(yīng)用程序管理的”。)CDI可能是此處的解決方案。 您可以生成請(qǐng)求范圍內(nèi)的EntityManager并將其注入所需的任何組件中。 看起來可能像這樣(在現(xiàn)實(shí)生活中,您還需要注意處理EM):

public class Resources {@PersistenceUnitEntityManagerFactory emf;@Produces @RequestScopedpublic EntityManager createEntityManager() {return emf.createEntityManager();} }

現(xiàn)在,在每個(gè)bean中我們都可以擁有:

@Stateless public class MyBean {@InjectEntityManager em; }

在構(gòu)成事務(wù)的不同組件之間共享應(yīng)用程序管理的持久性上下文似乎是一種非常干凈的方法。 但是,我擔(dān)心的是:知道由應(yīng)用程序管理的EntityManager事務(wù)性行為取決于創(chuàng)建它的位置 ,因此這種方法有時(shí)可能會(huì)給您帶來討厭的結(jié)果。 以下面的代碼為例( 我的Github項(xiàng)目中也提供了該類,該類正是在這里 ):

@Stateless @TransactionAttribute(TransactionAttributeType.NEVER) public class BeanABoundary {@Injectprivate EntityManager em;@EJBBeanB beanB;public void invoke() {em.getProperties();beanB.invoke(); }

請(qǐng)注意,BeanA是非事務(wù)性資源。 還要注意,我們在EntityManager上注入并調(diào)用了一些操作 (這使得注入實(shí)際上得以執(zhí)行。)現(xiàn)在,如果BeanB是事務(wù)性的,并且還注入并使用EntityManager –我們將以非事務(wù)性EntityManager結(jié)束,該操作不會(huì)拋出任何異常,并且不會(huì)將任何更改保存到數(shù)據(jù)庫 。

在舊的@PersistenceContext的情況下,我們將處于事務(wù)中,因?yàn)镋ntityManager將由容器管理,并且容器將知道當(dāng)前處于活動(dòng)狀態(tài)的事務(wù)。 容器負(fù)責(zé)在事務(wù)邊界之間共享EntityManager。 在顯示CDI生產(chǎn)者方法的情況下,CDI不知道運(yùn)行事務(wù),而只是共享EntityManager。

當(dāng)然,可以使用CDI并創(chuàng)建一個(gè)@Produces @PersistenceContext EntityManager em ,然后使用@Inject EntityManager 。 這將與@PersistenceContext EntityManager完全一樣,但是允許我們在產(chǎn)生EntityManager的單個(gè)位置定義(例如)持久性單元的名稱。 但是,如果我們要擁有一個(gè)應(yīng)用程序管理的EntityManager,則這不是一個(gè)選擇。

參考: 實(shí)體管理器的類型:由我們的JCG合作伙伴 Piotr Nowicki在Piotr Nowicki主頁博客上進(jìn)行的應(yīng)用程序管理的EntityManager 。

翻譯自: https://www.javacodegeeks.com/2013/03/types-of-entity-managers-application-managed-entitymanager.html

entitymanager

總結(jié)

以上是生活随笔為你收集整理的entitymanager_实体管理器的类型:应用程序管理的EntityManager的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。