日期:2014-05-16  浏览次数:20478 次

JTA事务和JDBC事务
一般情况下,J2EE应用服务器支持JDBC事务、JTA事务、容器管理事务。这里讨论JTA和JDBC事务的区别。这2个是常用的DAO模式事务界定方式。
JDBC 事务
JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。
★ 在jdbc中,事务操作缺省是自动提交。也就是说,一条对数据库的更新表达式代表一项事务操作,操作成功后,系统将自动调用commit()来提交,否则将调用rollback()来回滚。
★ 在jdbc中,可以通过调用setAutoCommit(false)来禁止自动提交。之后就可以把多个数据库操作的表达式作为一个事务,在操作完成后调用commit()来进行整体提交,倘若其中一个表达式操作失败,都不会执行到commit(),并且将产生响应的异常;此时就可以在异常捕获时调用 rollback()进行回滚。这样做可以保持多次更新操作后,相关数据的一致性,示例如下:

Java代码

 
 1.   try {  
   2.   
   3. conn =   
   4.   
   5. DriverManager.getConnection      
   6.   
   7. ("jdbc:oracle:thin:@host:1521:SID","username","userpwd";  
   8.   
   9.        conn.setAutoCommit(false);//禁止自动提交,设置回滚点  
  10.   
  11.        stmt = conn.createStatement();  
  12.   
  13. stmt.executeUpdate(“alter table …”); //数据库更新操作1  
  14.   
  15. stmt.executeUpdate(“insert into table …”); //数据库更新操作2  
  16.   
  17.        conn.commit(); //事务提交  
  18.   
  19.      }catch(Exception ex) {      
  20.   
  21.          ex.printStackTrace();  
  22.   
  23.          try {  
  24.   
  25.           conn.rollback(); //操作不成功则回滚  
  26.   
  27.           }catch(Exception e) {  
  28.   
  29. e.printStackTrace();  
  30.   
  31.            }  
  32.   
  33. }  

  try {

conn = 

DriverManager.getConnection    

("jdbc:oracle:thin:@host:1521:SID","username","userpwd";

       conn.setAutoCommit(false);//禁止自动提交,设置回滚点

       stmt = conn.createStatement();

stmt.executeUpdate(“alter table …”); //数据库更新操作1

stmt.executeUpdate(“insert into table …”); //数据库更新操作2

       conn.commit(); //事务提交

     }catch(Exception ex) {    

         ex.printStackTrace();

         try {

          conn.rollback(); //操作不成功则回滚

          }catch(Exception e) {

e.printStackTrace();

           }

}


JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。

JTA事务

JTA(Java Transaction API) 为 J2EE 平台提供了分布式事务服务。
要用 JTA 进行事务界定,应用程序要调用 javax.transaction.UserTransaction 接口中的方法。JTA事务需要application server提供支持,创建transactionManager对象,进行分布式事务。但是tomcat不提供transactionManager服务,jboss和weblogic提供支持。tomcat可以结合spring提供支持

例如: utx.begin();
   
Java代码

  
1. // ...  
   2.      DataSource ds = obtainXADataSource();  
   3.      Connection conn = ds.getConnection();  
   4.      pstmt = conn.prepareStatement("UPDATE MOVIES ...");  
   5.      pstmt.setString(1, "Spinal Tap");  
   6.      pstmt.executeUpdate();  
   7.      // ...  
   8.      utx.commit();  

 // ...
      DataSource ds = obtainXADataSource();
      Connection conn = ds.getConnection();
      pstmt = conn.prepareStatement("UPDATE MOVIES ...");
      pstmt.setString(1, "Spinal Tap");
      pstmt.executeUpdate();
      // ...
      utx.commit();


让我们来关注下面的话:
“用 JTA 界定事务,那么就需要有一个实现 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个 XADataSource 对象就是一个 XAConnection 对象的工厂。 XAConnection s 是参与 JTA 事务的 JDBC 连接。”
要使用JTA事务,必须使用XADataSource来产生数据库连接,产生的连接为一个XA连接。
XA连接(javax.sql.XAConnection)和非XA(java.sql.Connection)连接的区别在于:XA可以参与JTA的事务,而且不支持自动提交。
     Note:
Oracle, Sybase, DB2, SQL Server等大型数据库才支持XA, 支持分布事务。
My SQL 连本地都支持不好,更别说分布事务了。
JTA方式的实现过程:
   用XADataSource产生的XAConnection它扩展了一个getXAResource()方法,事务通过这个方法把它加入到事务容器中进行管理.对于调用者来说,根本看不到事务是如果管理的,你只要声明开始事务,告诉容器我下面的操作要求事务参与了,最后告诉事务说到这儿可以提交或回滚了, 别的都是黑箱操作。
在使用JTA之前,你必须首先实现一个Xid类用来标识事务(在普通情况下这将由事务管理程序来处理)。Xid包含三个元素:formatID、 gtrid(全局事务标识符)和bqual(分支修饰词标识符)。
下面的例子说明Xid的实现:
Java代码

 
 1. import javax.transaction.xa.*;   
   2. public class MyXid implemen