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

          EJB事務ZZ

          Posted on 2009-03-24 10:25 小強摩羯座 閱讀(1272) 評論(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表示沒有回滾。


          主站蜘蛛池模板: 临安市| 南江县| 崇州市| 同仁县| 田林县| 巴林右旗| 阳新县| 绥阳县| 霍林郭勒市| 怀集县| 榆林市| 马公市| 时尚| 台东市| 镇坪县| 丹东市| 石景山区| 上犹县| 建昌县| 景宁| 乌鲁木齐市| 红原县| 从化市| 伊川县| 龙胜| 广元市| 平原县| 娱乐| 商河县| 新晃| 阿拉善右旗| 日土县| 安达市| 防城港市| 林口县| 石渠县| 广南县| 密云县| 报价| 隆化县| 克什克腾旗|