EJB事务控制(CMT和BMT两种方式以及JTA事务)

一、EJB的事务管理分如下两个方面:

1、CMT(容器管理事务)

2、BMT(Bean管理事务)

 

二、CMT介绍:

  容器管理事务主要是通过容器自动控制事务的开启,提交和回滚,开发人员不需要手工编写代码,由容器来控制事务的边界,一般来说是业务方法的开始

是事务的开启,业务方法的结束是事务的提交部分,当程序遇到运行时异常,事务会自动回滚。如果遇到非运行时异常想要回滚事务的话可以用SessionCon

Text的setRollBackOnly()方法来达到目的。下面的例子是一个使用CMT的例子:(事务的控制我们一般放在Service层,而不是Dao层)

 

示例程序1:(参考publicEJB组件的NewhouseManagerImpl类)

@Stateless(name = "newhouseManager") //状态定义实列Bean 提供远程JNDI

@Remote(INewhouseManager.class)//定义远程接口

@Local(INewhouseManager.class)//定义本地接口

@TransactionManagement(TransactionManagementType.CONTAINER)  // 这里来定义是CMT还是BMT
public class NewhouseManagerImpl implements INewhouseManager{       

    @EJB(beanName = "newhouseDAO") //注入dao    

    private IGenericDAO<Newhouse, Integer> newhouseDAO;         

    @TransactionAttribute(TransactionAttributeType.REQUIRED)  //这里来定义事务的传播特性,如果调用该组件的客户方已经开启了事务则加入原事务,否则开启一个新事务    

     public Newhouse save(Newhouse entity) {        

             LogUtil.log("saving Newhouse instance", Level.INFO, null);        

    try {            

        LogUtil.log("save successful", Level.INFO, null);            

        entity.setBname("测试1:" + new Date());            

        newhouseDAO.create(entity); //插入第一条记录,此时事务还没有提交,数据库里面看不到该记录                       

        Newhouse entity2 = new Newhouse();            

        entity2.setBname("测试2");            

        entity2.setPath(null); // 这里设置path为null的话,会出现运行时异常,事务会回滚,entity1和entity2将不会插入到public库的newhouse表中            

        newhouseDAO.create(entity2);           

    } catch (RuntimeException re) {            

        LogUtil.log("save failed", Level.SEVERE, re);            

        re.printStackTrace();                 

         return null;    

    }

PS:这里要特别注意NewhouseDAO这个类,需要添加@TransactionAttribute(TransactionAttributeType.REQUIRED)这个注解,我们项目里面原来的事务传播属性

设置的是REQUIRES_NEW,这样会将原来的事务挂起,然后开启一个新的事务。

 

三、BMT介绍

  BMT主要是通过手工编程来实现事务的开启、提交和回滚,相对于CMT来说虽然增加了工作量,但是控制力度更细,而且更加灵活,我们可以再出现异常的时候回滚事务

,也可以通过JMS返回或者远程调用返回值来控制事务的回滚或提交;使用BMT需要用到UserTransaction这个类的实例来实现事务的begin、commit和rollback,可以通过

Ejb注解的方式获得这个类实例,也可以用EJBContext.getUserTransaction来获得。下面是一个使用BMT的例子:

示例程序2:

@Stateless(name = "newhouseManager") //状态定义实列Bean 提供远程JNDI

@Remote(INewhouseManager.class)//定义远程接口

@Local(INewhouseManager.class)//定义本地接口

@TransactionManagement(TransactionManagementType.BEAN) //设置为BMT事务
public class NewhouseManagerImpl implements INewhouseManager{               

@Resource    

private UserTransaction ut; //注入UserTransaction        

@EJB(beanName = "newhouseDAO") //注入dao    

private IGenericDAO<Newhouse, Integer> newhouseDAO;         

@TransactionAttribute(TransactionAttributeType.REQUIRED)  //设置事务的传播特性为required    

public Newhouse save(Newhouse entity) {        

   LogUtil.log("saving Newhouse instance", Level.INFO, null);        

  try {            

        ut.begin();            

        LogUtil.log("save successful", Level.INFO, null);            

        entity.setBname("测试1:" + new Date());            

        newhouseDAO.create(entity);              

        Newhouse entity2 = new Newhouse();            

        entity2.setBname("测试2");            

        entity2.setPath(null);            

        newhouseDAO.create(entity2);            

        ut.commit();                       

    } catch(RuntimeException e) {

      ut.rollBack();

           }.........................

          ..........................

           ........................

    }

 

 

测试效果和示例程序1一样

 

 

四、跨多个数据库的事务控制(JTA事务)

     如果想要在一个事务操作中控制多个数据库的操作,需要如下两步操作:

 

1、需要设置persistence.xml里面的datasouce支持jta事务,另外设置transaction-type为jta,如下所示

<persistence-unit name="public_master"  transaction-type="JTA">         

  <jta-data-source>java:/public_master_db</jta-data-source>      

<properties>             

  <property name="hibernate.dialect" value="com.jiwu.core.utils.BlobMySQLDialect"/>          

  <property name="hibernate.hbm2ddl.auto" value="update"/>          

  <property name="hibernate.show_sql" value="false" />      

</properties>   

</persistence-unit>            

<persistence-unit name="build_master"  transaction-type="JTA">         

  <jta-data-source>java:/build_master_db</jta-data-source>            

<property name="hibernate.dialect" value="com.jiwu.core.utils.BlobMySQLDialect"/>          

<property name="hibernate.hbm2ddl.auto" value="update"/>          

<property name="hibernate.show_sql" value="false" />      

</properties>   

</persistence-unit>

 

2、修改jboss安装目录下的\server\default\conf\jbossjta-properties.xml

在<properties depends="arjuna" name="jta">这个节点下,添加一个子节点<property name="com.arjuna.ats.jta.allowMultipleLastResources" value="true"/>

 

 

实例程序3:

@Stateless(name = "newhouseManager") //状态定义实列Bean 提供远程JNDI

@Remote(INewhouseManager.class)//定义远程接口

@Local(INewhouseManager.class)//定义本地接口

@TransactionManagement(TransactionManagementType.BEAN) //设置为BMT事务
public class NewhouseManagerImpl implements INewhouseManager{               

    @Resource     private UserTransaction ut; //注入UserTransaction        

     @EJB(beanName = "newhouseDAO") //注入dao    

    private IGenericDAO<Newhouse, Integer> newhouseDAO;    

          @EJB(beanName = "buildDAO") //注入houseDAO测试    

       private IGenericDAO<Build, Integer> buildDAO;  

          @TransactionAttribute(TransactionAttributeType.REQUIRED)  //设置事务的传播特性为required    

    public Newhouse save(Newhouse entity) {        

       LogUtil.log("saving Newhouse instance", Level.INFO, null);        

      try {            

         ut.begin();            

           LogUtil.log("save successful", Level.INFO, null);            

         entity.setBname("测试1:" + new Date());            

         newhouseDAO.create(entity);              

         Newhouse entity2 = new Newhouse();            

           entity2.setBname("测试2");            

           entity2.setPath(null); //这里不设置为null的话,不出现异常,entity1和entity2会插入到public库的newhouse表中,另外build库的build表中id为2的被删除            

         newhouseDAO.create(entity2);

         buildDAO.delete(2);

                  ut.commit();                       

    } catch(RuntimeException e) {

      ut.rollBack(); //出现异常,entity1和entity2不会插入到public库的newhouse表中,另外build库的build表中id为2的记录也不会删除

           }.........................

          ..........................

           ........................

   }     

转载于:https://www.cnblogs.com/alexisli/p/4011519.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值