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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实例详解 EJB 中的六大事务传播属性--转

發布時間:2025/4/5 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实例详解 EJB 中的六大事务传播属性--转 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

事務 (Transaction) 是訪問并可能更新數據庫中各種數據項的一個程序執行單元 (unit)。在關系數據庫中,一個事務可以是一條或一組 SQL 語句,甚至整個程序。它有通常被稱為 ACID 的原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持續性(Durability)四大特性:

原子性(Atomicity):一個事務是一個不可分割的工作單位,事務中包括的諸操作要么都做,要么都不做。

一致性(Consistency):事務必須是使數據庫從一個一致性狀態變到另一個一致性狀態。一致性與原子性是密切相關的。

隔離性(Isolation):一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的數據對并發的其他事務是隔離的,并發執行的各個事務之間不能互相干擾。

持久性(Durability):持續性也稱永久性(permanence),指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響。

在 Java EE 的應用開發中,事務的應用是必不可少的,同時由于方法調用的原因,比如方法 A 調用方法 B 的時候。如果方法 A 在事務環境中運行,那么方法 B 是否也要在事務中運行呢,方法 B 是要和方法 A 在同一個事務中運行還是新開起一個事物呢?等等。要弄清楚這些問題,就要牽涉到事務傳播屬性的問題,EJB 中針對不同的的情況提供了下面六種不同的事物傳播屬性:

Required:用該屬性標注的方法或組件總是在事務中運行。如果客戶端已經在事務中,則在原事務中運行;如果沒有事務,則開啟一個新事務,在其中運行。

Requires_New:方法或組件總是在新開啟的事務中運行。如果客戶端已經在事務中,則首先將原事務掛起,然后新開啟一個事務,在其中運行,新事務結束之后,原來事務從掛起點繼續執行;如果沒有事務,則開啟一個新事務,在其中運行。

Supports:和 Required 屬性的不同點是,在沒有事務的環境中不會開啟一個新事務;如果存在事務的話則加入其中運行,這點和 Reuqired 相同。

Not_Supported:如果事務已經存在的情況下,則原來的事務要掛起,然后調用標注該屬性的方法或組件,調用結束之后,繼續原來的事務;無事務環境中調用的時候,不開啟新事務,這點和 Supports 相同。

Mandatory:調用標注該屬性的方法或組件的客戶端,必須已經在事務中,如果不在事務中則會拋出異常;如果已經在事務中,則加入原來事務運行。和 Required 不同的是,該屬性不會自動開啟新的事務;

Never用 Never 屬性標注的方法或組件,不能在事務中運行。如果調用該方法或組件的客戶端已經在事務中,則拋出異常。

下面就實例詳細介紹一下 EJB 中這六種不同的事務傳播屬性。

前期準備工作

首先,我們創建如下幾個類,來作為我們后續中的實例。

清單 1. Address 實體 Bean
@Entity public class Address implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String country; private String city; private String street; private String postCode; private String TsAttribute; @Temporal(javax.persistence.TemporalType.TIMESTAMP) private Date createTime; // Getters and Setters }

我們在 Address 實體 Bean 中添加一些字段:

清單 2. Person 實體 Bean
@Entity public class Person implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String firstName; private String lastName; private int age; private String TsAttribute; @Temporal(javax.persistence.TemporalType.TIMESTAMP) private Date createTime; // Getters and Setters }

同樣我們在 Person 實體 Bean 中添加一些字段:

清單 3. 無狀態的 SessionBean CommonEJB
@Stateless public class CommonEJB implements CommonEJBRemote { @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override public void createAddress() { Address address = new Address(); /* * * 對 address 對象* 的屬性進行賦值* */ em.persist(address); } }

我們在 CommonEJB 中創建了一個名為 createAddress() 的業務方法,使用這個方法來持久化 Address 實體 bean,因此我們也使用 @PersistenceContext 注入了相應的持久化單元,我們將會將 Address 持久化到這個持久化單元對應的數據庫中。

清單 4. 無狀態的 SessionBean ClientEJB
@Stateless public class ClientEJB implements ClientEJBRemote { @EJB private CommonEJBRemote commonEJB; @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override public void createPerson() { Person person = new Person(); /*** 對 person 對象* 的屬性進行賦值**/em.persist(person); commonEJB.createAddress();// 調用 CommonEJB 中的 createAddress 方法} }

同樣,我們在 ClientEJB 創建了一個名為 createPerson() 的業務方法,使用這個方法來持久化 Person 實體 bean。稍有不同的是我們不僅注入了相應的持久化單元,而且注入了 CommonEJB 到這個 EJB 中,并且在 createPerson() 方法中調用了 CommonEJB 中的業務方法。

好了現在,我們所有的準備工作都已完成下面我們開始逐一介紹這六大事務傳播屬性。

傳播屬性實例祥解

Required

當一個方法的事務傳播屬性被設置成為“Required”的時候,說明該方法需要在事務的環境中運行。如果調用該方法的客戶端不在事務中,這個時候,當該方法執行的時候就會開啟一個新的事務;相反,如果調用該方法的方法已經運行在一個事務之中,那么該方法就會加入原來的事務運行。

下面舉例說明一下

清單 5. 調用 ClientEJB 的 Main 函數
public class Main { @EJB private static ClientEJBRemote clientEJB; public static void main(String[] args) { clientEJB.createPerson(); } }

我們使用 NetBeans 中獨有的技術來調用 EJB,這樣的話我們就不需要手動使用 JNDI 了,直接使用依賴注入的技術,在 main() 方法中注入我們要調用的 EJB,這里我們調用的是名為 ClientEJB 的 EJB。根據自 Java EE 5 引入的“Configuration by Exception”的原則,確省情況下這個 EJB 使用的是”Required”這個事務傳播屬性,根據”Required”事務傳播屬性的要求,ClientEJB 被 main() 方法調用的時候會開啟一個新的事務。

清單 6.ClientEJB 持久化 Person 實體 Bean
@Stateless public class ClientEJB implements ClientEJBRemote { @EJB private CommonEJBRemote commonEJB; @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override public void createPerson() { Person person = new Person(); person.setId(100l); person.setFirstName("Leo"); person.setLastName("Wang"); person.setAge(88); person.setTsAttribute("Required"); person.setCreateTime(new Date()); em.persist(person); commonEJB.createAddress(); System.out.println("----ClientEJB Excute completely!-------"); } }

在 ClientEJB 這個無狀態 EJB 中的 createPerson() 業務方法中我們持久化了一個 Person 對象到數據庫中。

清單 7.CommonEJB 持久化 Address 實體 Bean
@Stateless public class CommonEJB implements CommonEJBRemote { @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override @TransactionAttribute(TransactionAttributeType.REQUIRED) public void createAddress() { Address address = new Address(); address.setId(200l); address.setCountry("China"); address.setCity("Beijing"); address.setStreet("Long Jin"); address.setPostCode("102208"); address.setTsAttribute("REQUIRED"); address.setCreateTime(new Date()); em.persist(address); System.out.println("------ClientEJB Excute completely!---------"); } }

在 CommonEJB 這個無狀態 EJB 中的 createAddress () 業務方法中我們持久化了一個 Person 對象到數據庫中。

TransactionAttribute 這個注解的定義如下:

清單 8.TransactionAttribute 注解定義
@Target(value={METHOD,TYPE}) @Retention(value=RUNTIME)

從它的定義中可以看出,這個注解可以定義在類的層次上,也可以定義在方法上。如果兩個層次同時定義的話,定義在方法上的屬性會覆蓋定義在類層次上的屬性。EJB 中類層次上的和方法層次上的傳播屬性默認均為”Required”。

這里我們顯示地將 CommonEJB 中的 CreateAddress() 方法的傳播屬性設置成了”Required”,雖然我們沒有必要這么做,他確省就是”Required”。我們在 ClientEJB 中的 CreatePerson() 方法中調用了這個 CreateAddress() 方法,根據”Required”傳播屬性的定義,CreateAddress() 方法將會加入調用者 CreatePerson() 開啟的事務當中,成為其中的一部分。下面是這個程序運行的結果

圖 1.GlassFish 控制臺輸出

圖 1 顯示兩個方法均執正常行完畢,沒有任何異常拋出。

圖 2. 實體 Bean Person 對應的數據庫表

CreatePerson() 方法正常執行完畢后,ID 為 200 的人被持久化到數據庫中。

圖 3. 實體 Bean Address 對應的數據庫表

CreateAddress() 方法正常執行完畢后,ID 為 100 的地址被持久化到數據庫中。

這就說明這兩個方法均在事務的環境中進行了持久化的操作,且沒有回滾。

下面我們使用依賴注入,將 SessionContext 注入到 ClientEJB,并在 createPerson() 中調用 setRollbackOnly() 將這個方法所在的事務設置成 Doomed 事務。Doomed 事務就是那些鐵定要回滾的事務,無論他進行了什么操作,無論成功與否,都要回滾,這就是他的宿命。

清單 9. 客戶端 createPerson() 回滾
@Stateless public class ClientEJB implements ClientEJBRemote { @EJB private CommonEJBRemote commonEJB; @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Resource private SessionContext ctx; @Override public void createPerson() { Person person = new Person(); person.setId(100l); person.setFirstName("Leo"); person.setLastName("Wang"); person.setAge(88); person.setHeight(170); person.setWeight(65); person.setCreateTime(new Date()); em.persist(person); commonEJB.createAddress(); ctx.setRollbackOnly(); System.out.println("-----ClientEJB Excute completely!---------"); } }

這個時候 我們保持 CommonEJB 不變,然后執行這個程序。

使用同樣的辦法,我們將 ClientEJB 保持不變,將 CommonEJB 中的 createAddress() 方法所在的事務設置成 Doomed 事務,然后執行程序。

清單 10. 被調用者 createAddress() 回滾
@Stateless public class CommonEJB implements CommonEJBRemote { @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Resource private SessionContext ctx; @Override @TransactionAttribute(TransactionAttributeType.REQUIRED) public void createAddress() { Address address = new Address(); address.setId(200l); address.setCountry("China"); address.setCity("Beijing"); address.setStreet("Long Jin"); address.setPostCode("102208"); address.setCreateTime(new Date()); em.persist(address); ctx.setRollbackOnly(); System.out.println("--------ClientEJB Excute completely!--------"); } }

上述兩種情況,從控制臺上我們均可以看出兩個方法正確執行完畢,但是兩個方法中數據均沒有被持久化到數據庫中,這就是說,他們所在的事務一起進行了回滾。出現這樣的情況是因為,”Required”屬性是加入原有事務,也就是說它們處于同一個事物當中,一方滾另一方也回滾。

Requires_New

當一個方法的事務傳播屬性被設置成為“Requires_New”的時候。如果調用該方法的客戶端不在事務中,這個時候,當該方法執行的時候就會開啟一個新的事務;相反,如果調用該方法的方法已經運行在一個事務之中,那么該方法同樣會開啟一個新的事務,并在新事物中運行,而原來的事務則掛起,等待新開啟的事情執行完畢之后再繼續執行。

清單 11 .Requires_New 屬性中 ClientEJB 客戶端
@Stateless public class ClientEJB implements ClientEJBRemote { @EJB private CommonEJBRemote commonEJB; @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override public void createPerson() { Person person = new Person(); person.setId(88l); person.setFirstName("Tom"); person.setLastName("Zhang"); person.setAge(88); person.setTsAttribute("Required"); person.setCreateTime(new Date()); em.persist(person); commonEJB.createAddress(); System.out.println("------ClientEJB Excute completely!---------"); } }

我們仍然保持 ClientEJB 的默認屬性不變,而僅僅將 CommonEJB 中的 createAddress() 方法的事務傳播屬性設置成”Requires_New”,如清單 12 所示

清單 12. Requires_New 屬性中 CommonEJB
@Stateless public class CommonEJB implements CommonEJBRemote { @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void createAddress() { Address address = new Address(); address.setId(55l); address.setCountry("China"); address.setCity("Shanghai"); address.setStreet("Long Jin"); address.setPostCode("102208"); address.setTsAttribute("REQUIRES_NEW"); address.setCreateTime(new Date()); em.persist(address); System.out.println("----------ClientEJB Excute completely!--------"); } }

當我們運行程序的時候其結果如下,說明程序正確執行完畢,數據也持久化到了數據庫中

圖 4 .Person 表

CreatePerson() 方法正常執行完畢后,ID 為 88 的人被持久化到數據庫中。

圖 5 .Address 表

CreateAddress() 方法正常執行完畢后,ID 為 55 的地址被持久化到數據庫中。

下面我們將 ClientEJB 設置為 Doomed 事務,而保持 CommonEJB 不變,看看是什么情況。

外圍事務回滾,不影響新開啟的事務。

清單 13. Requires_New 屬性中被設定為 Doomed 的 ClientEJB
@Stateless public class ClientEJB implements ClientEJBRemote { @EJB private CommonEJBRemote commonEJB; @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Resource SessionContext ctx; @Override public void createPerson() { Person person = new Person(); person.setId(88l); person.setFirstName("Tom"); person.setLastName("Zhang"); person.setAge(88); person.setTsAttribute("Required"); person.setCreateTime(new Date()); em.persist(person); ctx.setRollbackOnly(); commonEJB.createAddress(); System.out.println("------ClientEJB Excute completely!---------"); } }

當我們執行完程序之后,Glass Fish 控制臺顯示程序正確執行沒有異常拋出,但是數據庫中顯示只有 Address 被持久化到了數據庫中。

圖 6.Address 表

這就因為 createPerson() 所在的事務進行了回滾,而 createAddress() 所在的事務沒有回滾。

內圍事務回滾,不影響外圍事務。

下面我們將 CommonEJB 設置為 Doomed 事務,而保持 ClientEJB 不變,看看是什么情況。

清單 14.Requires_New 屬性中被設定為 Doomed 的 CommonEJB
@Stateless public class CommonEJB implements CommonEJBRemote { @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Resource SessionContext ctx; @Override @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void createAddress() { Address address = new Address(); address.setId(55l); address.setCountry("China"); address.setCity("Shanghai"); address.setStreet("Long Jin"); address.setPostCode("102208"); address.setTsAttribute("REQUIRES_NEW"); address.setCreateTime(new Date()); em.persist(address); ctx.setRollbackOnly(); System.out.println("----------ClientEJB Excute completely!--------"); } }

當我們正確執行完程序之后,數據庫中只有 Person 的記錄,這就說明 createAddress() 所在的方法進行了回滾,而 createPerson() 沒有。

圖 7.Person 表

以上兩種情況說明,Require_New 開啟的是一個新事務,外圍事務也就是調用者或客戶端所在事務的回滾,不會影響到這個新開起的事務;同樣,新開起的事務的回滾與否對外圍事務也沒有任何影響。

Supports

當一個方法的事務傳播屬性被設置成為“Supports”的時候,如果調用該方法的客戶端不在事務中,這個時候,當該方法執行的時候不會開啟一個新的事務,仍會在無事務的環境中運行;相反,如果調用該方法的方法已經運行在一個事務之中,那么該方法就會加入原來的事務運行,這點和“Required”相同。

清單 15.Supports 屬性中 ClientEJB 客戶端
@Stateless public class ClientEJB implements ClientEJBRemote { @EJB private CommonEJBRemote commonEJB; @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override public void createPerson() { Person person = new Person(); person.setId(33l); person.setFirstName("Jerry"); person.setLastName("Leoo"); person.setAge(22); person.setTsAttribute("Required"); person.setCreateTime(new Date()); em.persist(person); commonEJB.createAddress(); System.out.println("------ClientEJB Excute completely!---------"); } }

我們仍然保持 ClientEJB 的默認屬性不變,而僅僅將 CommonEJB 中的 createAddress() 方法的事務屬性設置成“Supports“。

清單 16.Supports 屬性中 CommonEJB
@Stateless public class CommonEJB implements CommonEJBRemote { @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override @TransactionAttribute(TransactionAttributeType.SUPPORTS) public void createAddress() { Address address = new Address(); address.setId(66l); address.setCountry("USA"); address.setCity("NewYork"); address.setStreet("Seventh Avenue"); address.setPostCode("123-456"); address.setTsAttribute("SUPPORTS"); address.setCreateTime(new Date()); em.persist(address); System.out.println("----------ClientEJB Excute completely!--------"); } }

當我們執行之后,可以看到兩個方法中的數據均持久化到了數據庫中

圖 8.Person 表

圖 9.Address 表

當調用者自己新開起一個事務,或已經處于某個事務之中的時候,被調用者會加入調用者的事務。這樣調用者和被調用者就處于同一個事務之中,在任何一個方法內出現引起事務回滾的事件,調用者和被調用者都要回滾。

當調用者不在事務中運行,而被調用者的事務傳播屬性為“SUPPORTS”時,被調用者也不會開啟新事務,仍舊在無事務的環境中運行,這個時候和普通得 Java 方法之間的調用毫無區別,任何一個 Java 程序員對這種情況都會司空見慣,這里也不再贅敘。

Not_Supported

當一個方法的事務傳播屬性被設置成為“Not_Supported”的時候,如果調用該方法的客戶端不在事務中,這個時候,當該方法執行的時候也不會開啟一個新的事務,而仍是在無事務中的環境中運行,這點和用無事務的方法調用傳播屬性為”Suppots”的方法相同,不再贅敘;相反,如果調用該方法的客戶端已經運行在一個事務之中,那么原來的事務則掛起,等待被調用者在無事務的環境中運行完畢之后,再繼續執行原來掛起的事務,原來事務的回滾與否對被調用者均無影響。

清單 17.Not_Supported 屬性中 ClientEJB 客戶端
@Stateless public class ClientEJB implements ClientEJBRemote { @EJB private CommonEJBRemote commonEJB; @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override public void createPerson() { Person person = new Person(); person.setId(123l); person.setFirstName("Marry"); person.setLastName("Bush"); person.setAge(22); person.setTsAttribute("Required"); person.setCreateTime(new Date()); em.persist(person); commonEJB.createAddress(); System.out.println("------ClientEJB Excute completely!---------"); } }

ClientEJB 中 createPerson() 方法我們仍然使用默認傳播屬性,而將 CommonEJB 中的 createAddress() 的傳播屬性設置成了 Not_Supported。

清單 18.Not_Supported 屬性中 CommonEJB
@Stateless public class CommonEJB implements CommonEJBRemote { @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void createAddress() { /** 此處省略了一些業務處理的代碼 ,* 因為 persist(Object obj) 必須在事務中執行* 所以此處暫時不能使用**/System.out.println("----------ClientEJB Excute completely!--------"); } }

運行程序完畢之后,從圖 10 中可以看到 ID 為 123 的 Person 已經持久化到了數據庫中,說明 createPerson() 所在事務在調用 createAddress() 方法時,把事務掛起,當 createAddress() 執行完畢,繼續事務的過程中完成了提交。

圖 10.Person 表

如下所示,我們將 createPerson() 方法新開起的事務設定成 Doomed 事務,執行完畢后,由于事務的回滾,Person 數據并沒有持久化到數據庫中。而 createAddress() 方法一直在無事務的環境中運行,所以當外圍事務回滾的時候,對他并沒有人很影響。

清單 19.Not_Supported 屬性中 ClientEJB 客戶端
@Stateless public class ClientEJB implements ClientEJBRemote { @EJB private CommonEJBRemote commonEJB; @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Resource SessionContext ctx; @Override public void createPerson() { Person person = new Person(); person.setId(123l); person.setFirstName("Marry"); person.setLastName("Bush"); person.setAge(22); person.setTsAttribute("Required"); person.setCreateTime(new Date()); em.persist(person); ctx.setRollbackOnly(); commonEJB.createAddress(); System.out.println("------ClientEJB Excute completely!---------"); } }

Mandatory

當一個方法的事務傳播屬性被設置成為“Mandatory”的時候,說明這個方法必須在一個事務環境下執行。如果調用該方法的客戶端不在事務中,這個時候,調用該方法時,就會拋出 javax.ejb.EJBTransactionRequiredException 異常;相反,如果調用該方法的方法已經運行在一個事務之中,那么該方法就會加入原來的事務運行,這點和“Required”相同。

清單 20.Mandatory 屬性中 ClientEJB 客戶端
@Stateless public class ClientEJB implements ClientEJBRemote { @EJB private CommonEJBRemote commonEJB; @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override public void createPerson() { Person person = new Person(); person.setId(88l); person.setFirstName("Min"); person.setLastName("Zhao"); person.setAge(22); person.setTsAttribute("Required"); person.setCreateTime(new Date()); em.persist(person); commonEJB.createAddress(); System.out.println("------ClientEJB Excute completely!---------"); } }

我們仍然保持了 ClientEJB 中 createPerson() 方法的默認傳播屬性,而將 CommonEJB 中的 createAddress() 方法事務傳播屬性設置成了”Mandatory”。

清單 21.Mandatory 屬性中 CommonEJB
@Stateless public class CommonEJB implements CommonEJBRemote { @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override @TransactionAttribute(TransactionAttributeType.MANDATORY) public void createAddress() { Address address = new Address(); address.setId(66l); address.setCountry("Japan"); address.setCity("Tokyo"); address.setStreet("Seventh Avenue"); address.setPostCode("444-789"); address.setTsAttribute("MANDATORY"); address.setCreateTime(new Date()); em.persist(address); System.out.println("----------ClientEJB Excute completely!--------"); } }

運行結果如下圖所示,說明兩個方法都是在事務中得到了執行。由于使用“Mandatory”傳播屬性的方法是加入原來的外圍事務,也就是說它們處于同一個事務當中,所以在任何一個方法中如果調用 setRollbackOnly() 方法將事務設定成 Doomed 事務后,事務中的所有方法的持久化操作都會隨著事務的回滾而回滾。這里不再重復舉例。

圖 11.Person 表

圖 12.Address 表

如清單 22 我們把 ClientEJB 的傳播屬性修改為”Mandatory”,因為 Main() 不在事務中運行,所以在 Main() 方法中調用 ClientEJB 是就會拋出異常。

例如:

清單 22.Mandatory 屬性中 ClientEJB
@Stateless public class ClientEJB implements ClientEJBRemote { @EJB private CommonEJBRemote commonEJB; @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override @TransactionAttribute(TransactionAttributeType.MANDATORY) public void createPerson() { Person person = new Person(); person.setId(88l); person.setFirstName("Min"); person.setLastName("Zhao"); person.setAge(22); person.setTsAttribute("Required"); person.setCreateTime(new Date()); em.persist(person); commonEJB.createAddress(); System.out.println("------ClientEJB Excute completely!---------"); } }

當我們再次運行的時候,控制臺就會拋出如下異常:

圖 13.EJBTransactionRequiredException

Never

當一個方法的事務傳播屬性被設置成為“Never”的時候,說明這個方法必須在無事務環境下執行。如果調用該方法的方法不在事務中,該方法將會在無事務環境中運行;相反,如果調用該方法的方法已經運行在一個事務之中,那么調用該方法的時候就會拋出“RemoteException”異常。

清單 23.Never 屬性中的 ClientEJB 客戶端
@Stateless public class ClientEJB implements ClientEJBRemote { @EJB private CommonEJBRemote commonEJB; @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override public void createPerson() { Person person = new Person(); person.setId(88l); person.setFirstName("Ying"); person.setLastName("Tong"); person.setAge(22); person.setTsAttribute("Required"); person.setCreateTime(new Date()); em.persist(person); commonEJB.createAddress(); System.out.println("------ClientEJB Excute completely!---------"); } }

ClientEJB 中 createPerson() 方法采用了默認的傳播屬性,CommonEJB 中 createAddress() 方法使用了”Never”的傳播屬性。

清單 24.Never 屬性中的 CommonEJB
@Stateless public class CommonEJB implements CommonEJBRemote { @PersistenceContext(unitName = "Transaction-ejbPU") EntityManager em; @Override @TransactionAttribute(TransactionAttributeType.NEVER) public void createAddress() { Address address = new Address(); address.setId(66l); address.setCountry("Korea"); address.setCity("Souel"); address.setStreet("Tian Jian"); address.setPostCode("4444444"); address.setTsAttribute("NEVER"); address.setCreateTime(new Date()); em.persist(address); System.out.println("----------ClientEJB Excute completely!--------"); } }

當我們運行的時候控制臺拋出了如下圖所示的異常,由于程序未能正確執行,所以方法內持久化操作均不能完成,數據庫中也沒有相應的數據。

圖 14.Never 中拋出異常

綜上所述,EJB 中事務的傳播屬性可以用如下表格進行概括:

表 1. 事務傳播屬性總表
事務傳播屬性客戶端在事務中運行客戶端不在事務中運行
MANDATORY加入客戶端所在的事務拋出?TransactionRequiredException?異常
NEVER拋出?RemoteException?異常方法在無事務環境中運行
NOT_SUPPORTED客戶端的事務掛起,方法在無事務環境中運行,客戶端的事務繼續執行方法在無事務環境中運行
REQUIRED加入客戶端所在的事務為該方法新開起一個事務
REQUIRES_NEW客戶端的事務掛起,為該方法新開起一個事務,客戶端的事務繼續執行為該方法新開起一個事務
SUPPORTS加入客戶端所在的事務方法在無事務環境中運行

Nested

Spring 中還有一個沒有在 EJB 標準中定義的 Nested 的事務傳播屬性,這個屬性和 Requires_New 極為類似,同樣被已在事務環境中的 Client 調用的時候須開啟一個新事務。唯一不同的就是 Nested 事務傳播屬性,更像一個嵌套屬性,也就是說它新開起的這個事物要依附于父事務,如果父事務提交或者回滾了,它也需要跟著提交或者回滾。而 Requies_New 新開起的事務和父事務沒有這種關系,它們是完全獨立的兩個事務,一方提交或者回滾不影響另一方。因為這個并不是 Java EE 標準中的事務傳播屬性,所以在這里也就不再贅敘了,有興趣的讀者可以參看相關資料。

總結

邏輯層是 Java EE 項目開發中的核心層,而事物是邏輯層中的靈魂所在,所以掌握好邏輯層中的事物處理方式,對 Java EE 開發起到關鍵的作用,雖然開源領域中,事務處理的方式各有不同,但是在邏輯層事物傳播屬性中,上面所提到的六大傳播屬性,已經被大家認可并廣泛接受,已經被不同的邏輯層中間件普遍采用,使用已經很廣,所以掌握了上面的那些傳播屬性的使用方法,我們就可以在以后 Java EE 項目邏輯層的開發中以不變應萬變了。

原文:http://www.ibm.com/developerworks/cn/java/j-lo-springejbtrans/

轉載于:https://www.cnblogs.com/davidwang456/p/3833101.html

總結

以上是生活随笔為你收集整理的实例详解 EJB 中的六大事务传播属性--转的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: xnxx国产 | 日韩一区在线免费观看 | 欧美一级淫片免费视频魅影视频 | 国产精品综合在线 | 亚洲成年人免费观看 | 日本中文字幕一区 | 日日摸日日添日日碰9学生露脸 | 日本一区二区三区四区五区 | 国产成人 综合 亚洲 | av毛片在线免费看 | 日韩aⅴ视频 | 手机在线观看免费av | 欧美特黄 | 人人狠狠综合久久亚洲 | 午夜寂寞福利 | 国语av | 在线观看黄av | 久久88| 久久精品国产大片免费观看 | 97人人超| 亚洲一二三精品 | 国产精品区一区二 | 一本色道久久88 | 国产精品久久久久影院 | 日本公妇乱淫免费视频一区三区 | 亚洲一区福利视频 | 最近中文字幕在线视频 | 中文成人在线 | 亚洲国产精品一区二区久久hs | 91小仙女jk白丝袜呻吟 | 91精品国产91久久久久久 | 久久成人乱码欧美精品一区二区 | 可以免费看的av毛片 | 国产精品视频一二三区 | 日本视频一区二区 | 九九九九九九精品 | 亚洲国产精品成人综合色在线婷婷 | 国产福利一区二区三区视频 | 色屁屁草草影院ccyycom | 深爱五月综合网 | 午夜黄色大片 | 女同hd系列中文字幕 | 老头av | 国产91精品高潮白浆喷水 | 欧美xxxxbbb | 超碰在线91| 日韩欧美一区二区区 | 香蕉影院在线观看 | 西欧free性满足hd老熟妇 | 日批视频免费在线观看 | aaa级片 | 91动态图| av免费网站观看 | 中文字幕二区在线观看 | 日批视频在线免费看 | 久章操| 色天天av | 色a视频 | 手机看片1024在线 | 中文字幕乱码视频 | 成人久久18免费网站图片 | 色图18p | 欧美激情成人在线 | 欧美色图日韩 | 91视频xxx | 欧美三日本三级少妇三级99观看视频 | 91麻豆精品91久久久久同性 | 九七影院在线观看免费观看电视 | 人妻人人澡人人添人人爽 | 日本免费电影一区二区三区 | 激情四射婷婷 | 免费在线播放视频 | 啄木乌欧美一区二区三区 | 欧美第二区 | 国产又粗又猛又大爽 | 少妇在军营h文高辣 | 日韩不卡视频在线观看 | 免费超爽大片黄 | 97精品在线视频 | 日本视频www| 精品国产亚洲一区二区麻豆 | 国产女人18水真多毛片18精品 | 九九热这里只有 | 日韩一区欧美一区 | 国产福利小视频 | 欧美日韩1区 | 综合av网 | 久久久久xxxx | 乱熟女高潮一区二区在线 | 99视频+国产日韩欧美 | 日本欧美一区二区三区不卡视频 | 激情小视频在线观看 | 五月婷婷综合在线 | 欧美狂猛xxxxx乱大交3 | 中文字幕av在线免费 | 超碰婷婷 | 少妇与公做了夜伦理69 | 伊人9| 亚洲成人免费网站 |