java事务管理

java事务管理主要分成三个部分:JDBC,JTA,容器事务

他们之间的差异:
jdbc事务控制的局限性在一个数据库链接内,但是其使用简单
jta事务的功能强大,事务可以跨越多个数据库或者多个DAO,但是使用也比较复杂
容器事务,主要是指j2ee应用服务器提供的事务管理局限于EJB应用的使用(spring的事务管理)

JDBC:
在Java中使用事务处理,首先要求数据库支持事务。如使用MySQL的事务功能,就要求MySQL的表类型为Innodb才支持事务。否则,在Java程序中做了commit或rollback,但在数据库中根本不能生效。 
在Connection类中提供了3个控制事务的方法: 
(1) setAutoCommit(Boolean autoCommit):设置是否自动提交事务; 
(2) commit();提交事务; 
(3) rollback();回滚事务;


在jdbc api中,默认的情况为自动提交事务,也就是说,每一条对数据库的sql语句代表一项事务,操作成功后,系统自动调用commit()来提交,否则将调用rollback()来撤消事务。 
在jdbc api中,可以通过调用setAutoCommit(false) 来禁止自动提交事务。然后就可以把多条更新数据库的sql语句做为一个事务,在所有操作完成之后,调用commit()来进行整体提交。倘若其中一项 sql操作失败,就不会执行commit()方法,而是产生相应的sqlexception,此时就可以捕获异常代码块中调用rollback()方法撤消事务。 


事务处理为什么要在servie层呢,而不是在DAO层?
首先,在service层,基本上是每一个方法都对应着一个具体的业务,有些时候,一个业务可能需要操作到不同的表,也就是用到不同的DAO接口,所以事务处理最好是在service层。

由于jdbc事务管理的缺陷是只能针对同一个数据库链接中,所以如果需要从两个或以上的数据库里取得数据的话,会有很大的缺陷,针对需要查询两个或以上数据库的时候(也叫分布式事务),幸运的是通常情况下,JavaEE兼容的应用服务器,例如:Weblogic,Websphere,JBoss,Glassfish等都有这种分布式事务处理的组件。 

JTA:
Java事务API(JTA;Java Transaction API)和它的同胞Java事务服务(JTS;Java Transaction Service),为J2EE平台提供了分布式事务服务。一个分布式事务(distributed transaction)包括一个事务管理器(transaction manager)和一个或多个资源管理器(resource manager)。一个资源管理器(resource manager)是任意类型的持久化数据存储。事务管理器(transaction manager)承担着所有事务参与单元者的相互通讯的责任。JTA事务比JDBC事务更强大。一个JTA事务可以有多个参与者,而一个JDBC事务则被限定在一个单一的数据库连接。

在使用中,我们需要使用UserTransaction这个类,里边有这几个方法:
begin:开启一个事务
commit:提交当前事务
rollback:回滚当前事务
setRollbackOnly:把当前事务标记为回滚
setTransactionTimeout:设置事务的事件,超过这个事件,就抛出异常,回滚事务
使用了UserTransaction就能把普通的JDBC操作直接转成JTA操作,JTA对DataSource、Connection和Resource 都是有要求的,只有符合XA规范,并且实现了XA规范的相关接口的类才能参与到JTA事务中来,目前主流的数据库都支持XA规范。

下面是一个示例:
public void JtaTransfer() { 
        javax.transaction.UserTransaction tx = null;
        java.sql.Connection conn = null;
         try{ 
             tx = (javax.transaction.UserTransaction) context.lookup("java:comp/UserTransaction");  //取得JTA事务,本例中是由Jboss容器管理
             javax.sql.DataSource ds = (javax.sql.DataSource) context.lookup("java:/XAOracleDS");  //取得数据库连接池,必须有支持XA的数据库、驱动程序  
             tx.begin();
            conn = ds.getConnection();

             // 将自动提交设置为 false,
             //若设置为 true 则数据库将会把每一次数据更新认定为一个事务并自动提交
             conn.setAutoCommit(false);

             stmt = conn.createStatement(); 
             // 将 A 账户中的金额减少 500 
             stmt.execute("\
             update t_account set amount = amount - 500 where account_id = 'A'");
             // 将 B 账户中的金额增加 500 
             stmt.execute("\
             update t_account set amount = amount + 500 where account_id = 'B'");

             // 提交事务
             tx.commit();
             // 事务提交:转账的两步操作同时成功
         } catch(SQLException sqle){            
             try{ 
                 // 发生异常,回滚在本事务中的操做
              tx.rollback();
                 // 事务回滚:转账的两步操作完全撤销
                 stmt.close(); 
                 conn.close(); 
             }catch(Exception ignore){ 

             } 
             sqle.printStackTrace(); 
         } 
     }


 

你可能感兴趣的:(java)