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

EJB事务ZZ

Posted on 2009-03-24 10:25 小强摩羯座 阅读(1248) 评论(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表示没有回滚。



只有注册用户登录后才能发表评论。


网站导航: