posts - 195, comments - 34, trackbacks - 0, articles - 1

          EJB事務ZZ

          Posted on 2009-03-24 10:25 小強摩羯座 閱讀(1268) 評論(0)  編輯  收藏 所屬分類: Java
          EJB事務
          在ejb組件設計中,組件行為有時需要具備事務特征,即使用事務保證組件行為的完整性,使組件要么執行成功,要么回到起點.等價沒有執行!
          討論事務時要明確兩個概念:
          事務范圍
          算法的可恢復性與事務性:如果事務中的算法動作結果受事務提交或者回滾影響,則該算法具有事務可恢復性,否則就不具備事務可恢復性.
          事務在本質上就是一個管理系列算法動作一致性的對象!ejb提供了兩種事務類型:聲明性和程序性事務
          聲明性事務:由ejb容器負責事務對象的 生成,管理,銷毀;具體算法在事務上的注冊,事務的提交和回滾等
          主要介紹聲明性的事務:
             ejb容器為其中的所有的ejb組件提供了一種默認的事務模式:Requires
          在該模式下面,組件中的方法如果在事務環境下被調用(即客戶端調用了該組件的方法),則方法中的邏輯會被添加到客戶端的事務環境中,和客戶端的程序使用相同的事務控制對象.如果不在事務環境中調用(在客戶端沒有調用該組件中的方法),ejb容器就創建新的事務對象,管理該方法中的所有邏輯.
          例如:
          ejb組件:
             @Statefull
          public class personmanager inplements IPersonAdmin{
          @PersistenceContext(unitName="mydb")
          private EntityManager manager;
          @EJB(mappedName="MySession/remote")
          private IPersonAdmin mytools;
          public List<person> QueryAll(){
          ....
          }
          public void createPerson(Person p){
          Person pobj=new Person();
          pobj.setName("ziaoxioa");
          #1 manager.persist(pobj);
          #2 mytools.createPerson(p);
          #3 manager.persist(null);
          }
          客戶代碼:
          ...
          myinf.createPerson(p);
          ...
          默認情況下,ejb讀物起會為ejb組件中的所有方法配置一中requires型的事務服務.在這種事務模式下面,如果方法被在事務環境下調用,方法就使用客戶端事務對象和事務環境ruguo不在事務環境中被調用,則ejb容器就會創建新的事務對象和環境來負責管理該方法的邏輯完整性!由于上面的#3錯誤,所以數據庫中不會添加任何記錄!
          ejb容器為ejb組件添加的默認的事務策略能夠滿足多數情況下的算法要求,特殊情況下,可以通過@TransactionAttribute和<container-transaction>標記修改組件的默認事務策略!如下:
          <ejb-jar
                 xmlns="http://java.sun.com/xml/ns/javaee"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                                     http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
                 version="3.0">
          <assembly-descriptor>
             <container-transaction>
                <method>
                  <ejb-name>MySession</ejb-name>
                  <method-name>createPerson</method-name>
                </method>
                <trans-attribute>RequiresNew</trans-attribute>
             </container-transaction>
          </assembly-descriptor>
          </ejb-jar>
          @TransactionAttribute(REQUIRES_NEW)
          public void createPerson(Person p){
          manager.persist(p);
          }
          這樣MySession中的createPerson方法事務修改成了RequiesNew模式,在這種模式下,ejb容器不論客戶端是否具有事務特征,為createPerson創建一個新的事務對象,此時兩個createPerson在完全不同的事務對象控制下,所以#2可以提交到數據庫中,#1,#3則回滾
          聲明性事務模式:
           Required  ejb容器為ejb組件方法提供的默認事務模式,在這種模式下,如果調用程序具備自身的事務對象,則組件方法就和客戶程序使用相同的事務對象,否則ejb容器就會創建新的事務對象來管理組件方法邏輯
           Supports  在這種模式下,如果調用程序具備事務特征,則組件方法就會調用調用程序事務對象管理自身邏輯,如果調用程序不包含任何的事務對象,則組件方法也處于無事務管理狀態
           NotSupported  這種模式下,組件方法不支持事務,同時也會忽略掉調用程序中的事務對象,組件方法中的邏輯不受客戶程序事務的提交或回滾的影響
           RequiresNew  在這種模式下,忽略調用程序具備的事務特征,ejb容器會新創建一個新的事務對象管理組件方法邏輯
           Mandatory  ejb容器不會為該方法創建新的事務管理對象。該組件方法的調用程序必須提供事務對象,處于事務環境中,否則程序將產生異常javax.ejb.EJBTransactionRequiredException
           Never  這種模式下,該方法不會被ejb容器提供事務對象服務,并且調用程序也不能處于事務環境中,否則將產生EJBException異常

          下面的程序首先清楚組件上的默認事務模式,然后在為方法設定具體事務屬性:
          <assembly-descriptor>
             <container-transaction>
                <method>
                  <ejb-name>MySession</ejb-name>
                  <method-name>*</method-name>
                </method>
                <trans-attribute>NotSupported</trans-attribute>
             </container-transaction>
             <container-transaction>
                <method>
                  <ejb-name>MySession</ejb-name>
                  <method-name>createPerson</method-name>
                </method>
                <trans-attribute>Required</trans-attribute>
             </container-transaction>
          </assembly-descriptor>
          聲明性事務的控制:
          @Stateless
          /*10*/public class PersonManager implements IPersonAdmin
          /*11*/{
          /*12*/     @Resource
          /*13*/     private EJBContext ctx;
          /*14*/     @PersistenceContext(unitName="mydb")     
          /*15*/   private EntityManager manager;
          /*16*/   @EJB(mappedName="MySession/remote")
          /*17*/   private IPersonAdmin mytools;
          /*18*/   public List<Person> QueryAll()
          /*19*/   {     
          /*20*/         Query q=manager.createQuery("from Person c");
          /*21*/         List results=q.getResultList();
          /*22*/                 List<Person> result=(List<Person>)results;
          /*23*/                 return result;
          /*24*/   }
          /*25*/   public void createPerson(Person p)
          /*26*/   {
          /*27*/         Person pobj=new Person();     
          /*28*/             pobj.setName("zhanghao");     
          /*29*/             pobj.setAge(new Integer(32)); 
          /*30*/             pobj.setSex("male");          
          /*31*/         manager.persist(pobj);
          /*32*/         boolean result=ctx.getRollbackOnly();
          /*33*/         if(!result)
          /*34*/         {
          /*35*/            ctx.setRollbackOnly();                 
          /*36*/         }
          /*37*/   }
          /*38*/}
          該方法使用gejb容器提供的默認的事務模式,事務會在方法結束時自動提交。
          getRollbackOnly()返回房前事務的狀態,true表示已經回滾,false表示沒有回滾。


          主站蜘蛛池模板: 子长县| 北流市| 嵩明县| 香格里拉县| 高陵县| 金寨县| 滨州市| 泰安市| 崇信县| 淮南市| 利辛县| 白沙| 铜梁县| 中牟县| 乌兰察布市| 沙湾县| 兴安县| 天镇县| 景洪市| 手机| 云浮市| 宁河县| 安达市| 泗洪县| 巴东县| 德保县| 江达县| 申扎县| 泾源县| 六盘水市| 纳雍县| 隆子县| 万宁市| 蒲江县| 宁都县| 安吉县| 靖远县| 山阳县| 湘潭市| 广灵县| 南华县|