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

    歡迎訪問 生活随笔!

    生活随笔

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

    编程问答

    jpa 事务嵌套事务_JPA 2 | EntityManagers,事务及其周围的一切

    發(fā)布時(shí)間:2023/12/3 编程问答 27 豆豆
    生活随笔 收集整理的這篇文章主要介紹了 jpa 事务嵌套事务_JPA 2 | EntityManagers,事务及其周围的一切 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

    jpa 事務(wù)嵌套事務(wù)

    介紹

    對(duì)我來說,最令人困惑和不清楚的事情之一是,作為Java開發(fā)人員,一直是圍繞事務(wù)管理的謎團(tuán),尤其是JPA如何處理事務(wù)管理。 事務(wù)什么時(shí)候開始,什么時(shí)候結(jié)束,實(shí)體的持久化方式,持久性上下文等等。 諸如Spring之類的框架也無助于理解概念,因?yàn)樗鼈兲峁┝肆硪粚映橄?#xff0c;這使事情難以理解。 在今天的帖子中,我將嘗試揭露JPA關(guān)于實(shí)體管理的規(guī)范,其事務(wù)規(guī)范以及如何更好地理解該概念如何幫助我們有效地設(shè)計(jì)和編碼的某些秘密。 我們將努力保持討論

    盡管我們將同時(shí)研究Java SE(其中沒有Java EE容器)和基于Java EE的示例。

    基本概念

    在深入探討更多細(xì)節(jié)之前,讓我們快速完成一些基礎(chǔ)課程及其在JPA中的含義。

  1. EntityManager –一個(gè)管理實(shí)體的持久狀態(tài)(或生命周期)的類。
  2. 持久性單元 –是實(shí)體類的命名配置。
  3. 持久性上下文 –是一組托管的實(shí)體實(shí)例。 實(shí)體類是持久性單元配置的一部分。
  4. 托管實(shí)體 –如果實(shí)體實(shí)例是持久性上下文的一部分,并且該實(shí)體管理器可以對(duì)其執(zhí)行操作,則該實(shí)體實(shí)例將受到管理。
  5. 從上面的第一點(diǎn)和第三點(diǎn),我們可以推斷出實(shí)體管理器總是管理持久性上下文。 因此,如果我們了解持久性上下文,我們將了解EntityManager。

    細(xì)節(jié)

    JPA中的EntityManager

    JPA中定義了EntityManager的三種主要類型。

    • 容器管理和交易范圍的實(shí)體管理器
    • 容器管理和擴(kuò)展范圍實(shí)體管理器
    • 應(yīng)用程序管理的實(shí)體管理器

    現(xiàn)在,我們將更詳細(xì)地介紹其中的每一個(gè)。

    容器管理的實(shí)體管理器

    當(dāng)應(yīng)用程序的一個(gè)容器(例如Java EE容器或任何其他自定義容器,例如Spring)管理實(shí)體管理器的生命周期時(shí),該實(shí)體管理器被稱為“容器管理”。 獲取容器管理的EntityManager的最常見方法是在EntityManager屬性上使用@PersistenceContext批注。 這是定義EntityManager的示例。

    public class EmployeeServiceImpl implements EmployeeService { @PersistenceContext(unitName="EmployeeService") EntityManager em; public void assignEmployeeToProject(int empId, int projectId) { Project project = em.find(Project.class, projectId); Employee employee = em.find(Employee.class, empId); project.getEmployees().add(employee); employee.getProjects().add(project); }

    在上面的示例中,我們?cè)贓ntityManager類型實(shí)例變量上使用了@PersistenceContext批注。 PersistenceContext批注具有屬性“ unitName”,用于標(biāo)識(shí)該上下文的持久性單元。

    容器管理的實(shí)體管理器有兩種形式:

  6. 交易范圍的實(shí)體管理器
  7. 擴(kuò)展范圍實(shí)體管理器
  8. 請(qǐng)注意,上述范圍實(shí)際上是指實(shí)體管理器管理的持久性上下文的范圍。 它不是EntityManager本身的范圍。

    讓我們依次查看它們中的每一個(gè)。

    交易范圍實(shí)體管理器

    這是應(yīng)用程序中最常用的實(shí)體管理器。 同樣在上面的示例中,我們實(shí)際上是在創(chuàng)建事務(wù)作用域?qū)嶓w管理器。 每當(dāng)解析由@PersistenceContext創(chuàng)建的引用時(shí),都會(huì)返回事務(wù)作用域?qū)嶓w管理器。

    使用事務(wù)作用域?qū)嶓w管理器的最大好處是它是無狀態(tài)的。 這也使事務(wù)范圍的EntityManager線程安全,因此實(shí)際上無需維護(hù)。 但是我們只是說EntityManager管理實(shí)體的持久狀態(tài),而實(shí)體的持久狀態(tài)是注入EntityManager的持久性上下文的一部分。 那么,上述關(guān)于無國籍狀態(tài)的說法又如何呢?

    答案在于所有容器管理的實(shí)體管理器都依賴于JTA事務(wù)。 每次在實(shí)體管理器上調(diào)用操作時(shí),容器代理(容器在實(shí)例化時(shí)在實(shí)體管理器周圍創(chuàng)建一個(gè)代理)都會(huì)檢查JTA事務(wù)上是否存在任何持久性上下文。 如果找到一個(gè),則實(shí)體管理器將使用此持久性上下文。 如果找不到,則將創(chuàng)建一個(gè)新的持久性上下文并將其與事務(wù)關(guān)聯(lián)。

    讓我們以上面討論的相同示例來了解實(shí)體管理器和事務(wù)創(chuàng)建的概念。

    public class EmployeeServiceImpl implements EmployeeService { @PersistenceContext(unitName="EmployeeService") EntityManager em; public void assignEmployeeToProject(int empId, int projectId) { Project project = em.find(Project.class, projectId); Employee employee = em.find(Employee.class, empId); project.getEmployees().add(employee); employee.getProjects().add(project); }

    在上面的示例中,assignEmployeeToProject方法的第一行正在EntityManager上調(diào)用find方法。 查找調(diào)用將強(qiáng)制容器檢查現(xiàn)有交易。 是否存在事務(wù)(例如,對(duì)于Java EE中的無狀態(tài)會(huì)話Bean,容器在每次調(diào)用Bean上的方法時(shí)都保證事務(wù)可用)或不存在。 如果事務(wù)不存在,它將拋出異常。 如果存在,它將檢查持久性上下文是否存在。 自從第一次調(diào)用EntityManager的任何方法以來,持久性上下文尚不可用。 然后,實(shí)體管理器將創(chuàng)建一個(gè)并使用它來查找項(xiàng)目bean實(shí)例。

    在下一個(gè)查找調(diào)用中,實(shí)體管理器已經(jīng)具有關(guān)聯(lián)的事務(wù)以及與其關(guān)聯(lián)的持久性上下文。 它使用相同的事務(wù)來查找員工實(shí)例。 在方法的第二行結(jié)束時(shí),將同時(shí)管理項(xiàng)目和員工實(shí)例。 在方法調(diào)用結(jié)束時(shí),將提交事務(wù),并保留人員和員工的托管實(shí)例。 要記住的另一件事是,當(dāng)事務(wù)結(jié)束時(shí),持久性上下文消失了。

    擴(kuò)展范圍實(shí)體管理器

    如果并且當(dāng)您希望持久性上下文在方法范圍之外可用時(shí),請(qǐng)使用具有擴(kuò)展范圍的實(shí)體管理器。 理解擴(kuò)展范圍實(shí)體管理器的最好方法是以一個(gè)類為例,該類需要維護(hù)某種狀態(tài)(該狀態(tài)是由于諸如myEntityManager.find(“ employeeId”)之類的事務(wù)請(qǐng)求而創(chuàng)建的,然后使用該雇員),并且通過各種業(yè)務(wù)方法共享狀態(tài)。

    因?yàn)镻ersistence Context在方法調(diào)用之間共享并且用于維護(hù)狀態(tài),所以除非您在有狀態(tài)會(huì)話Bean中使用它們(容器負(fù)責(zé)使其成為線程安全的),否則它通常不是線程安全的。 重申一下,如果您使用的是Java EE容器,則將在Stateful Session Bean(帶有@Stateful注釋的類)內(nèi)使用擴(kuò)展范圍實(shí)體管理器。 如果您決定在有狀態(tài)bean之外使用它,則該容器不能保證您可以安全地執(zhí)行線程操作,而必須自己處理。 如果您使用的是像Spring這樣的第三方容器,情況也是如此。

    讓我們看一下使用狀態(tài)會(huì)話Bean時(shí)Java EE環(huán)境中擴(kuò)展作用域?qū)嶓w管理器的示例。

    該示例中的目標(biāo)是創(chuàng)建一個(gè)業(yè)務(wù)類,該業(yè)務(wù)類具有在LibraryUser Entity實(shí)例上工作的業(yè)務(wù)方法。 讓我們將此具有業(yè)務(wù)接口UserManagementService的業(yè)務(wù)類LibraryUserManagementService命名。 LibraryUserManagementService在LibraryUsers實(shí)體實(shí)例上工作。 圖書館可以將多本書借給LibraryUser。

    這是描述上述情況的有狀態(tài)會(huì)話Bean的示例。

    @Stateful public class LibraryUserManagementService implements UserManagementService { @PersistenceContext(unitName="UserService") EntityManager em; LibraryUser user; public void init(String userId) { user = em.find(LibraryUser.class, userId); } public void setUserName(String name) { user.setName(name); } public void borrowBookFromLibrary(BookId bookId) { Book book = em.find(Book.class, bookId); user.getBooks().add(book); book.setLendingUser(user); } // ... @Remove public void finished() { } }

    在上面使用用戶實(shí)例的情況下,更自然的是先獲得一個(gè)實(shí)例,然后逐步進(jìn)行操作,只有完成后,我們才應(yīng)保留用戶實(shí)例。 但是,問題在于實(shí)體管理器是事務(wù)范圍的。 這意味著init將在其自身的事務(wù)中運(yùn)行(因此具有其自身的持久性上下文),而roweBookFromLibrary將在其自身的事務(wù)中運(yùn)行。 結(jié)果,init方法一結(jié)束,用戶對(duì)象就變得不受管理。

    為了確切地解決此類問題,我們使用PersistenceContextType.EXTENDED類型的實(shí)體管理器。

    這是帶有PersistenceContextType EXTENDED的修改后的示例,可以很好地工作。

    @Stateful public class LibraryUserManagementService implements UserManagementService { @PersistenceContext(unitName="UserService" , type=PersistenceContextType.EXTENDED) EntityManager em;LibraryUser user; public void init(String userId) { user = em.find(LibraryUser.class, userId); } public void setUserName(String name) { user.setName(name); } public void borrowBookFromLibrary(BookId bookId) { Book book = em.find(Book.class, bookId); user.getBooks().add(book); book.setLendingUser(user); } // ... @Remove public void finished() { } }

    在上述場景中,用于管理用戶實(shí)例的PersistenceContext是由Java EE容器在Bean初始化時(shí)創(chuàng)建的,并且在調(diào)用完成的方法(在該時(shí)間提交事務(wù))之前可用。

    應(yīng)用范圍的實(shí)體管理器

    不是由容器而是由應(yīng)用程序本身創(chuàng)建的實(shí)體管理器是應(yīng)用程序范圍的實(shí)體管理器。 為了使定義更清晰,每當(dāng)我們通過在EntityManagerFactory實(shí)例上調(diào)用createEntityManager來創(chuàng)建實(shí)體管理器時(shí),實(shí)際上是在創(chuàng)建應(yīng)用程序范圍的實(shí)體管理器。 所有基于Java SE的應(yīng)用程序?qū)嶋H上都使用應(yīng)用程序范圍的實(shí)體管理器。 JPA為我們提供了一個(gè)Persistence類,該類用于最終創(chuàng)建應(yīng)用程序范圍的實(shí)體管理器。

    以下是如何創(chuàng)建應(yīng)用程序范圍的EM的示例:

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPersistenceUnit"); EntityManager em = emf.createEntityManager();

    請(qǐng)注意,要?jiǎng)?chuàng)建應(yīng)用程序范圍的EntityManager,在應(yīng)用程序的META-INF文件夾中需要有一個(gè)persistence.xml文件。

    EntityManager可以通過兩種方式創(chuàng)建。 上面已經(jīng)顯示了一個(gè)。 創(chuàng)建EntityManager的另一種方法是將一組屬性作為參數(shù)傳遞給
    createEntityManagerFactory方法。

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPersistenceUnit" , myProperties); EntityManager em = emf.createEntityManager();

    如果要?jiǎng)?chuàng)建自己的應(yīng)用程序托管實(shí)體管理器,請(qǐng)確保在每次使用完它后都將其關(guān)閉。 這是必需的,因?yàn)槟F(xiàn)在正在管理應(yīng)如何以及何時(shí)創(chuàng)建和使用EntityManager。

    交易管理

    交易與實(shí)體直接相關(guān)。 實(shí)質(zhì)上,管理事務(wù)意味著要管理實(shí)體生命周期(創(chuàng)建,更新,刪除)的管理方式。 理解事務(wù)管理的另一個(gè)關(guān)鍵是要了解持久性上下文如何與事務(wù)交互。 值得注意的是,從最終用戶的角度來看,即使我們使用EntityManager的實(shí)例,EntityManager的唯一作用是確定持久性上下文的生存期。 它在決定持久化上下文應(yīng)如何表現(xiàn)方面沒有任何作用。 重申一下,持久性上下文是一組實(shí)體實(shí)例的托管集合。 每當(dāng)事務(wù)開始時(shí),Persistence Context實(shí)例都會(huì)與之關(guān)聯(lián)。 當(dāng)事務(wù)結(jié)束時(shí)(例如,提交),持久性上下文將被刷新并與事務(wù)解除關(guān)聯(lián)。

    JPA支持兩種類型的事務(wù)管理類型。

    • 資源本地交易
    • JTA或全球交易

    資源本地事務(wù)是指JDBC驅(qū)動(dòng)程序的本機(jī)事務(wù),而JTA事務(wù)是指JEE服務(wù)器的事務(wù)。 資源本地事務(wù)涉及單個(gè)事務(wù)資源,例如JDBC連接。 每當(dāng)在單個(gè)事務(wù)中需要兩個(gè)或更多資源(例如JMS連接和JDBC連接)時(shí),都可以使用JTA事務(wù)。
    容器管理的實(shí)體管理器始終使用JTA事務(wù),因?yàn)槿萜髫?fù)責(zé)事務(wù)生命周期管理并在多個(gè)事務(wù)資源中產(chǎn)生事務(wù)。 應(yīng)用程序管理的實(shí)體管理器可以使用資源本地事務(wù)或JTA事務(wù)。

    通常,在JTA或全局事務(wù)中,第三方事務(wù)監(jiān)控器會(huì)在事務(wù)中獲取不同的事務(wù)資源,為提交做準(zhǔn)備,最后提交事務(wù)。 首先準(zhǔn)備事務(wù)資源(通過空運(yùn)行)然后提交(或回滾)的過程稱為兩階段提交。

    有關(guān)XA協(xié)議的附帶說明 –在全球交易中,交易監(jiān)視器必須不斷與不同的交易資源進(jìn)行對(duì)話。 不同的交易資源會(huì)說不同的語言,因此交易監(jiān)視器可能無法理解。 XA是一個(gè)協(xié)議規(guī)范,為事務(wù)監(jiān)視器與不同的事務(wù)資源進(jìn)行交互提供了通用基礎(chǔ)。 JTA是說XA的全球事務(wù)監(jiān)控器規(guī)范,因此能夠管理多個(gè)事務(wù)資源。 兼容Java EE的服務(wù)器具有內(nèi)置的JTA實(shí)現(xiàn)。其他容器(例如Spring)可以自己編寫或使用其他實(shí)現(xiàn)(例如Java Open Transaction Manager,JBoss TS等)來支持JTA或全局事務(wù)。

    持久性上下文,事務(wù)和實(shí)體管理器

    持久性上下文可以與單個(gè)或多個(gè)事務(wù)關(guān)聯(lián),也可以與多個(gè)實(shí)體管理器關(guān)聯(lián)。 持久性上下文已向事務(wù)注冊(cè),以便在提交事務(wù)時(shí)可以刷新持久性上下文。 事務(wù)開始時(shí),實(shí)體管理器將查找活動(dòng)的持久性上下文實(shí)例。 如果不可用,它將創(chuàng)建一個(gè)并將其綁定到事務(wù)。 通常,持久性上下文的范圍與事務(wù)緊密相關(guān)。 當(dāng)事務(wù)結(jié)束時(shí),與該事務(wù)關(guān)聯(lián)的持久性上下文實(shí)例也結(jié)束。 但是有時(shí),在大多數(shù)情況下,在Java EE世界中,我們需要事務(wù)傳播,這是在單個(gè)事務(wù)中的不同實(shí)體管理器之間共享單個(gè)持久性上下文的過程。

    持久性上下文可以有兩個(gè)范圍:

    • 事務(wù)范圍的持久性上下文
    • 擴(kuò)展范圍的持久性上下文

    我們已經(jīng)討論了事務(wù)/擴(kuò)展范圍的實(shí)體管理器,并且我們也知道實(shí)體管理器可以是事務(wù)或擴(kuò)展范圍的。 關(guān)系不是偶然的。 事務(wù)范圍的實(shí)體管理器創(chuàng)建事務(wù)范圍的持久性上下文。 擴(kuò)展范圍實(shí)體管理器使用擴(kuò)展持久性上下文。 擴(kuò)展持久性上下文的生命周期與Java EE環(huán)境中的有狀態(tài)會(huì)話Bean相關(guān)聯(lián)。

    讓我們簡要地討論這些持久性上下文

    事務(wù)范圍的持久性上下文

    TSPC僅在需要時(shí)由實(shí)體管理器創(chuàng)建。 僅當(dāng)首次調(diào)用實(shí)體管理器上的方法時(shí),事務(wù)作用域?qū)嶓w管理器才創(chuàng)建TSPC。 因此,持久性上下文的創(chuàng)建是懶惰的。 如果已經(jīng)存在傳播的持久性上下文,則實(shí)體管理器將使用該持久性上下文。

    了解持久性上下文傳播對(duì)于識(shí)別和調(diào)試代碼中與事務(wù)相關(guān)的問題非常重要。 讓我們看一個(gè)如何傳播事務(wù)范圍的持久性上下文的示例。

    ItemDAOImpl.java:

    public class ItemDAOImpl implements ItemDAO { @PersistenceContext(unitName="ItemService") EntityManager em; LoggingService ls; @TransactionAttribute()public void createItem(Item item) { em.persist(item); ls.log(item.getId(), "created item"); } // ... }

    LoggingService.java:

    public class LoggingService implements AuditService { @PersistenceContext(unitName="ItemService") EntityManager em; @TransactionAttribute()public void log(int itemId, String action) { // verify item id is valid if (em.find(Item.class, itemId) == null) { throw new IllegalArgumentException("Unknown item id"); } LogRecord lr = new LogRecord(itemId, action); em.persist(lr); } }

    調(diào)用ItemDAOImpl的createItem方法時(shí),將在實(shí)體管理器實(shí)例上調(diào)用persist方法。 假設(shè)這是對(duì)實(shí)體管理器方法的第一次調(diào)用。 實(shí)體管理器將查找單元名稱為“ ItemService”的任何傳播的持久性上下文。 它找不到一個(gè),因?yàn)檫@是對(duì)實(shí)體管理器的第一個(gè)調(diào)用。 因此,它創(chuàng)建了一個(gè)新的持久性上下文實(shí)例并將其附加到自身。 然后,它繼續(xù)保存Item對(duì)象。 持久化項(xiàng)目對(duì)象后,我們將調(diào)用以記錄剛剛持久化的項(xiàng)目信息。 請(qǐng)注意,LoggingService有其自己的EnitityManager實(shí)例,方法日志中具有注釋@TransactionAttribute(如果在Java EE envt中并且將bean聲明為EJB,則不需要此注釋)。
    由于TransactionAttribute的默認(rèn)TransactionAttributeType為REQUIRED,因此LoggingService中的實(shí)體管理器將查找以前的事務(wù)中可能可用的任何持久性上下文。 它找到一個(gè)在ItemDAOImpl的createItem方法內(nèi)部創(chuàng)建的對(duì)象,并使用相同的對(duì)象。 這就是為什么即使實(shí)際項(xiàng)目尚未持久到數(shù)據(jù)庫(因?yàn)樯形刺峤皇聞?wù)),LoggingService中的實(shí)體管理器仍能夠找到它,因?yàn)槌志眯陨舷挛囊褟腎temDAOImpl傳播到LoggingService 。

    擴(kuò)展持久性上下文

    事務(wù)范圍持久性上下文是為每個(gè)事務(wù)創(chuàng)建的(在不傳播的情況下),而擴(kuò)展持久性上下文僅創(chuàng)建一次,并由管理擴(kuò)展持久性上下文生命周期的類范圍內(nèi)的所有事務(wù)使用。 對(duì)于Java EE,由狀態(tài)會(huì)話Bean管理擴(kuò)展的持久性上下文的生命周期。 有狀態(tài)會(huì)話bean的創(chuàng)建是EAGER。 如果是容器托管事務(wù),則在類上的方法被調(diào)用后立即創(chuàng)建它。 對(duì)于應(yīng)用程序管理的事務(wù),將在調(diào)用userTransaction.begin()時(shí)創(chuàng)建。

    摘要

    在這篇博客文章中,已經(jīng)討論了很多東西,實(shí)體管理器,事務(wù)管理,持久性上下文,所有這些東西如何相互作用以及如何相互配合。

    我們討論了容器管理的實(shí)體管理器和應(yīng)用程序管理的實(shí)體管理器,事務(wù)范圍和擴(kuò)展范圍持久性上下文,事務(wù)傳播之間的區(qū)別。 該博客的大部分材料是閱讀了精彩的書: Pro JPA 2的結(jié)果 。 如果您想更深入地了解JPA的工作原理,我建議您閱讀它。

    參考: JPA 2 | JavaWorld博客博客中的JCG合作伙伴 Anuj Kumar提供了EntityManagers,Transactions及其周圍的一切 。

    翻譯自: https://www.javacodegeeks.com/2013/06/jpa-2-entitymanagers-transactions-and-everything-around-it.html

    jpa 事務(wù)嵌套事務(wù)

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的jpa 事务嵌套事务_JPA 2 | EntityManagers,事务及其周围的一切的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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