ejb事务管理

[转载自http://www.diybl.com/course/3_program/java/javaxl/20100719/459982.html]

[http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction3.html] 

 

一、前言
    在语音门户的开发过程中,出现了在发生异常的情况下事务没有正确会滚,导致数据的不一致型,在分析过程中发现是由于在处理异常方法不正确导致,所抛出的异常未能使事物回滚,那么怎样处理异常才能正确使事物回滚,下面将就EJB中的事务管理做出一些说明
二、EJB中事务处理的两种方式
在EJB中处理事务有两种方式,一种是由容器管理事务,一种是由Bean管理事务,在任何Bean中都可以使用容器管理事务,会话Bean和消息驱动Bean可以使用Bean管理事务,实体Bean不能使使用Bean管理事务。
(一)、容器管理事务
     容器管理事务简化了开发,因为企业Bean不用编码来显式制定事务界限。代码不包括开始结束事务的语句。典型的,容器会在一个企业Bean的方法被调用前立即开始一个事务,在这个方法退出以前提交这个事务。每个方法都关联一个事务。在一个方法中不允许嵌套或多个的事务存在。容器管理事务不需要所有的方法都关联事务。当部署一个Bean时,通过设定部署描述符中的事务属性来决定方法是否关联事务和如何关联事务
1、    事务的属性
一个事务的属性控制了事务的使用范围。图 1-1说明了为什么控制事务的范围很重要。图中,method-A开始一个事务然后调用Bean-2中的method-B.它运行在method-A开始的事务中还是重新执行一个新的事务?结果要看method-B中的事务属性
你可以为整个企业Bean或者单个方法指定事务属性。如果你为整个企业Bean和它某个方法各指定一个事务属性,为该方法指定的事务属性优先。当为单个方法指定事务属性时,不同类型企业Bean的要求也不同。会话Bean需要为商业方法定义属性属性,但create方法不需要定义事务属性。实体Bean需要为商业方法、create方法、remove方法和查找(finder)方法定义事务属性。Message-driven Bean需要为 onMessage方法指定属性事务,而且只能是Required和NotSupported其中之一。
(二) 、容器管理事务的回滚
在以下两中情况下,事务将回滚。
第一,    如果产生一个系统异常,容器将自动回滚该事务。
系统异常是指应用程序的支撑服务出现异常。这样的异常例子有:不能得到数据库连接,数据库满造成SQL语句插入失败,一个lookup方法找不到需要的对象等等。如果企业Bean遇到一个系统级的问题,它将抛出javax.ejb.EJBException,容器会把该异常包装到一个 RemoteException异常中返回给客户端。因为EJBException是RutimeException的子类,所以你不需要将它列在 throws子句中。当一个系统异常发生时,EJB容器可能会销毁企业Bean实例,因此系统异常不能被客户端处理,它需要系统管理员的干涉
第二,    由于EJBException作为系统异常,他继承自RutimeException,所以经过验证表明当抛出一个继承自 RutimeException的自定义异常时EJB容器也会自动回滚该事务,抛出普通的继承自Exception的应用程序异常容器不回自动回滚该事务
第三,    通过调用EJBContext接口SetRollbackOnly方法,Bean方法通知容器回滚该事务。如果Bean抛出一个普通的非继承自RutimeException应用异常,事务将不会自动回滚,但可以调用SetRollbackOnly回滚。例如
public class serviceRegBean implements SessionBean {
    SessionContext sessionContext;
    public void ejbCreate() throws CreateException {
    }
    public void ejbRemove() {
    }
    public void ejbActivate() {
    }
    public void ejbPassivate() {
    }
    public void setSessionContext(SessionContext sessionContext) {
        this.sessionContext = sessionContext;
    }
    public void updateData() throws   ThirdgsException {
        try {
           //更新操作一
           //更新操作二
        }
        catch (Exception ex) {
            //发生异常回滚事务
            sessionContext.setRollbackOnly();
            ex.printStackTrace();
            throw new ThirdgsException();
        }
    }
}
其中的ThirdgsException为继承自Exception的异常
(三) 、Bean管理事务
容器管理事务不支持嵌套事务,Bean管理事务支持嵌套事务,所以需要嵌套事务时可以采用Bean管理事务,使用Bean管理事务需要我们显式的设置事务的属性,需要我们自己编码管理事务,我门可以采用下面两种方式在Bean中管理事务
1、JDBC事务
JDBC 事务通过DBMS事务管理器来控制。你可能会为了使用会话Bean中的原有代码而采用JDBC事务将这些代码封装到一个事务中。使用JDBC事务,要调用 java.sql.Connection接口的commit和rollback方法。事务启动是隐式的。一个事务的从最近的提交、回滚或连接操作后的第一个SQL的语句开始。(这个规则通常是正确的,但可能DBMS厂商的不同而不同),例如
public void ship (String productId, String orderId, int quantity) {
try {
      //需要通知DBMS不要自动提交每个SQL语句
      con.setAutoCommit(false);
      updateOrderItem(productId, orderId);
      updateInventory(productId, quantity);
      con.commit();

   } catch (Exception ex) {
       try {
          con.rollback();
          throw new EJBException("Transaction failed: " +
             ex.getMessage());
       } catch (SQLException sqx) {
           throw new EJBException("Rollback failed: " +
              sqx.getMessage());
       }
   }
}
2、JTA事务
    JTA 是Java Transaction API 的缩写。这些API 允许你用独立于具体的事务管理器实现的方法确定事务界限。J2EE SDK 事务管理器通过Java事务服务(Java Transaction Service, JTS)实现。但是你的代码并不直接调用JTS中的方法,而是调用JTA 方法来替代,JTA方法会调用底层的JTS实现。
    JTA事务被J2EE 事务管理器管理。你可能需要使用一个JTA事务,因为它能够统一操作不同厂商的数据库。一个特定DBMS的事务管理器不能工作在不同种类的数据库上。然而J2EE事务管理器仍然有一个限制??它不支持嵌套事务。就是说,它不能在前一个事务结束前启动另一个事务。
??要自己确定事务界限,可以调用 javax.transaction.UserTransaction接口的begin、commit和rollback方法来确定事务界限(该接口只能在SessionBean中使用,实体Bean不允许使用用户自定义的)。下面选自TellerBean类的代码示范了UserTransaction的用法。begin和commit方法确定了数据库操作的事务界限,如果操作失败则调用rollback回滚事务并抛出EJBException异常。

public void withdrawCash(double amount) {
UserTransaction ut = context.getUserTransaction();
try {
      ut.begin();
      updateChecking(amount);
      machineBalance -= amount;
      insertMachine(machineBalance);
      ut.commit();
   } catch (Exception ex) {
       try {
          ut.rollback();
       } catch (SystemException syex) {
           throw new EJBException
              ("Rollback failed: " + syex.getMessage());
       }
       throw new EJBException
          ("Transaction failed: " + ex.getMessage());
    }
}

你可能感兴趣的:(java,bean,exception,数据库,jdbc,ejb)