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()进行回滚。这样做可以保持多次更新操作后,相关数据的一致性,示例如下: 

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 接口中的方法。例如:
 utx.begin(); 

 // ...
      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的实现:
 

import javax.transaction.xa.*; 
public class MyXid implements Xid 
{ 
 protected int formatId; 
 protected byte gtrid[]; 
 protected byte bqual[]; 
 public MyXid() 
 { 
 } 
 public MyXid(int formatId, byte gtrid[], byte bqual[]) 
 { 
  this.formatId = formatId; 
  this.gtrid = gtrid; 
  this.bqual = bqual; 
 } 

 public int getFormatId() 
 { 
  return formatId; 
 } 

 public byte[] getBranchQualifier() 
 { 
  return bqual; 
 } 

 public byte[] getGlobalTransactionId() 
 { 
  return gtrid; 
 } 

}

其次,你需要创建一个你要使用的数据库的数据源:

public DataSource getDataSource() 
 throws SQLException 
 { 
  SQLServerDataSource xaDS = new 
  com.merant.datadirect.jdbcx.sqlserver.SQLServerDataSource(); 
  xaDS.setDataSourceName("SQLServer"); 
  xaDS.setServerName("server"); 
  xaDS.setPortNumber(1433); 
  xaDS.setSelectMethod("cursor"); 
  return xaDS; 
} 


例1?这个例子是用“两步提交协议”来提交一个事务分支:  

XADataSource xaDS; 
XAConnection xaCon; 
XAResource xaRes; 
Xid xid; 
Connection con; 
Statement stmt; 
int ret; 
xaDS = getDataSource(); 
xaCon = xaDS.getXAConnection("jdbc_user", "jdbc_password"); 
xaRes = xaCon.getXAResource(); 
con = xaCon.getConnection(); 
stmt = con.createStatement(); 
xid = new MyXid(100, new byte[]{0x01}, new byte[]{0x02}); 
try { 
  xaRes.start(xid, XAResource.TMNOFLAGS); 
  stmt.executeUpdate("insert into test_table values (100)"); 
  xaRes.end(xid, XAResource.TMSUCCESS); 
  ret = xaRes.prepare(xid); 
  if (ret == XAResource.XA_OK) { 
    xaRes.commit(xid, false); 
   } 
} 
catch (XAException e) { 
 e.printStackTrace(); 
} 
finally { 
 stmt.close(); 
 con.close(); 
 xaCon.close(); 
}

当然,实际过程中,我们不需要写这些代码,这些代码是JTA最终的实现代码。 
关于“两步提交协议”,可以参看下面的文章:
 

http://www.jspcn.net/htmlnews/11049371131251752.html 



选择最好的方式 
用 JDBC API 进事务界定来构建 DAO 类的。这些 DAO 类可以总结如下: 

事务界定代码嵌入在 DAO 类中。 
DAO 类使用 JDBC API 进行事务界定。 
调用者不能界定事务。 
事务范围局限于单个 JDBC 连接。 
JDBC 事务并不总是适合复杂的企业应用程序。如果您的事务要跨越多个 DAO 或者多个数据库,那么下列实现策略也许更合适: 

事务用 JTA 界定。 
事务界定代码从 DAO 中分离出来。 
调用者负责界定事务。 
DAO 加入一个全局事务。 
JDBC 方式由于其简单性而具有吸引力,JTA方式提供了更大的灵活性。您所选择的实现将取决于应用程序的特定需求。 


XADataSource例子:
 

<?xml version="1.0" encoding="UTF-8"?>

<!-- ===================================================================== -->
<!--    -->
<!--  JBoss Server Configuration    -->
<!-- Thanks to Horia Muntean <horia@bvb.ro>   -->
<!-- ===================================================================== -->

<!-- $Id: db2-xa-ds.xml,v 1.1.2.1 2003/05/30 18:25:57 d_jencks Exp $ -->


<datasources>
   <!--
       XADatasource for DB2 V8.1 (app driver)
       copy $db2_install_dir/java/db2java.zip into $jboss_install_dir/server/default/lib
   -->

   <xa-datasource>
     <jndi-name>DB2XADS</jndi-name>
     <xa-datasource-class>COM.ibm.db2.jdbc.DB2XADataSource</xa-datasource-class>
     <xa-datasource-property name="DatabaseName">yout_database_name</xa-datasource-property>
     <xa-datasource-property name="User">your_user</xa-datasource-property>
     <xa-datasource-property name="Password">your_password</xa-datasource-property>
   </xa-datasource>
</datasources>


转载自:http://walsh.iteye.com/blog/258002



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值