﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-风人园-文章分类-J2EE</title><link>http://www.blogjava.net/wuxufeng8080/category/10540.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 03:30:15 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 03:30:15 GMT</pubDate><ttl>60</ttl><item><title>JTA和JDBC事务 (ZT)</title><link>http://www.blogjava.net/wuxufeng8080/articles/60359.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Thu, 27 Jul 2006 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/60359.html</guid><description><![CDATA[
		<h2> </h2>
		<div class="postbody">
				<p> 一般情况下，J2EE应用服务器支持JDBC事务、JTA事务、容器管理事务。这里讨论JTA和JDBC事务的区别。这2个是常用的DAO模式事务界定方式。<br /><font color="#ff1493">JDBC 事务</font><br /> JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式：自动提交和手工提交。例如如下片断：<br /> import java.sql.*;<br />      import javax.sql.*;</p>
				<p>      // ...<br />      DataSource ds = obtainDataSource();<br />      Connection conn = ds.getConnection();<br />      conn.setAutoCommit(false);<br />      // ...<br />      pstmt = conn.prepareStatement("UPDATE MOVIES ...");<br />      pstmt.setString(1, "The Great Escape");<br />      pstmt.executeUpdate();<br />      // ...<br />      conn.commit();<br />      // ...</p>
				<p> JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。<br /><font color="#ff1493">JTA事务<br /></font> JTA(Java Transaction API) 为 J2EE 平台提供了分布式事务服务。<br /> 要用 JTA 进行事务界定，应用程序要调用 javax.transaction.UserTransaction 接口中的方法。例如：<br /> utx.begin();<br />      // ...<br />      DataSource ds = obtainXADataSource();<br />      Connection conn = ds.getConnection();<br />      pstmt = conn.prepareStatement("UPDATE MOVIES ...");<br />      pstmt.setString(1, "Spinal Tap");<br />      pstmt.executeUpdate();<br />      // ...<br />      utx.commit();</p>
				<p> 让我们来关注下面的话：<br /> “用 JTA 界定事务，那么就需要有一个实现 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个 XADataSource 对象就是一个 XAConnection 对象的工厂。 XAConnection s 是参与 JTA 事务的 JDBC 连接。”<br /> 要使用JTA事务，必须使用XADataSource来产生数据库连接，产生的连接为一个XA连接。<br /> XA连接（javax.sql.XAConnection）和非XA（java.sql.Connection）连接的区别在于：XA可以参与JTA的事务，而且不支持自动提交。<br />     Note:<br />Oracle, Sybase, DB2, SQL Server等大型数据库才支持XA, 支持分布事务。 <br />My SQL 连本地都支持不好，更别说分布事务了。<br /><font color="#ff1493">JTA方式的实现过程</font>：<br />   用XADataSource产生的XAConnection它扩展了一个getXAResource()方法,事务通过这个方法把它加入到事务容器中进行管理.对于调用者来说,根本看不到事务是如果管理的,你只要声明开始事务,告诉容器我下面的操作要求事务参与了,最后告诉事务说到这儿可以提交或回滚了,别的都是黑箱操作。<br /> 在使用JTA之前，你必须首先实现一个Xid类用来标识事务（在普通情况下这将由事务管理程序来处理）。Xid包含三个元素：formatID、gtrid（全局事务标识符）和bqual（分支修饰词标识符）。<br /> 下面的例子说明Xid的实现：</p>
				<p>import javax.transaction.xa.*; <br />public class MyXid implements Xid <br />{ <br />　protected int formatId; <br />　protected byte gtrid[]; <br />　protected byte bqual[]; <br />　public MyXid() <br />　{ <br />　} <br />　public MyXid(int formatId, byte gtrid[], byte bqual[]) <br />　{ <br />　　this.formatId = formatId; <br />　　this.gtrid = gtrid; <br />　　this.bqual = bqual; <br />　} </p>
				<p>　public int getFormatId() <br />　{ <br />　　return formatId; <br />　} </p>
				<p>　public byte[] getBranchQualifier() <br />　{ <br />　　return bqual; <br />　} </p>
				<p>　public byte[] getGlobalTransactionId() <br />　{ <br />　　return gtrid; <br />　} </p>
				<p>}<br /> 其次，你需要创建一个你要使用的数据库的数据源：</p>
				<p>public DataSource getDataSource() <br />　throws SQLException <br />　{ <br />　　SQLServerDataSource xaDS = new <br />　　com.merant.datadirect.jdbcx.sqlserver.SQLServerDataSource(); <br />　　xaDS.setDataSourceName("SQLServer"); <br />　　xaDS.setServerName("server"); <br />　　xaDS.setPortNumber(1433); <br />　　xaDS.setSelectMethod("cursor"); <br />　　return xaDS; <br />} </p>
				<p>　　例1?这个例子是用“两步提交协议”来提交一个事务分支：</p>
				<p>XADataSource xaDS; <br />XAConnection xaCon; <br />XAResource xaRes; <br />Xid xid; <br />Connection con; <br />Statement stmt; <br />int ret; <br />xaDS = getDataSource(); <br />xaCon = xaDS.getXAConnection("jdbc_user", "jdbc_password"); <br />xaRes = xaCon.getXAResource(); <br />con = xaCon.getConnection(); <br />stmt = con.createStatement(); <br />xid = new MyXid(100, new byte[]{0x01}, new byte[]{0x02}); <br />try { <br />　　xaRes.start(xid, XAResource.TMNOFLAGS); <br />　　stmt.executeUpdate("insert into test_table values (100)"); <br />　　xaRes.end(xid, XAResource.TMSUCCESS); <br />　　ret = xaRes.prepare(xid); <br />　　if (ret == XAResource.XA_OK) { <br />　　　　xaRes.commit(xid, false); <br />　　　} <br />} <br />catch (XAException e) { <br />　e.printStackTrace(); <br />} <br />finally { <br />　stmt.close(); <br />　con.close(); <br />　xaCon.close(); <br />}<br /> 当然，实际过程中，我们不需要写这些代码，这些代码是JTA最终的实现代码。<br />关于“两步提交协议”，可以参看下面的文章：<br /><a href="http://www.jspcn.net/htmlnews/11049371131251752.html"><font color="#1d58d1">http://www.jspcn.net/htmlnews/11049371131251752.html</font></a></p>
				<p> <a href="http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html"><font color="#1d58d1">http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html</font></a></p>
				<p>
						<br />
						<font color="#ff1493">选择最好的方式<br /></font>用 JDBC API 进事务界定来构建 DAO 类的。这些 DAO 类可以总结如下：</p>
				<p>事务界定代码嵌入在 DAO 类中。 <br />DAO 类使用 JDBC API 进行事务界定。 <br />调用者不能界定事务。 <br />事务范围局限于单个 JDBC 连接。 <br />JDBC 事务并不总是适合复杂的企业应用程序。如果您的事务要跨越多个 DAO 或者多个数据库，那么下列实现策略也许更合适：</p>
				<p>事务用 JTA 界定。 <br />事务界定代码从 DAO 中分离出来。 <br />调用者负责界定事务。 <br />DAO 加入一个全局事务。 <br />JDBC 方式由于其简单性而具有吸引力，JTA　方式提供了更大的灵活性。您所选择的实现将取决于应用程序的特定需求。<br />XADataSource例子：<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;</p>
				<p>&lt;!-- ===================================================================== --&gt;<br />&lt;!--    --&gt;<br />&lt;!--  JBoss Server Configuration    --&gt;<br />&lt;!-- Thanks to Horia Muntean &lt;<a href="mailto:horia@bvb.ro"><font color="#1d58d1">horia@bvb.ro</font></a>&gt;   --&gt;<br />&lt;!-- ===================================================================== --&gt;</p>
				<p>&lt;!-- $Id: db2-xa-ds.xml,v 1.1.2.1 2003/05/30 18:25:57 d_jencks Exp $ --&gt;</p>
				<p>
						<br />&lt;datasources&gt;<br />   &lt;!--<br />       XADatasource for DB2 V8.1 (app driver)<br />       copy $db2_install_dir/java/db2java.zip into $jboss_install_dir/server/default/lib<br />   --&gt;</p>
				<p>   &lt;xa-datasource&gt;<br />     &lt;jndi-name&gt;DB2XADS&lt;/jndi-name&gt;<br />     &lt;xa-datasource-class&gt;COM.ibm.db2.jdbc.DB2XADataSource&lt;/xa-datasource-class&gt;<br />     &lt;xa-datasource-property name="DatabaseName"&gt;yout_database_name&lt;/xa-datasource-property&gt;<br />     &lt;xa-datasource-property name="User"&gt;your_user&lt;/xa-datasource-property&gt;<br />     &lt;xa-datasource-property name="Password"&gt;your_password&lt;/xa-datasource-property&gt;<br />   &lt;/xa-datasource&gt;<br />&lt;/datasources&gt;<br /><br />引用：<br /> <a href="http://www.jspcn.net/htmlnews/11049371131251752.html"><font color="#1d58d1">http://www.jspcn.net/htmlnews/11049371131251752.html</font></a><br /><a href="http://www-128.ibm.com/developerworks/cn/java/j-dao/"><font color="#1d58d1">http://www-128.ibm.com/developerworks/cn/java/j-dao/</font></a><br /><a href="http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html"><font color="#1d58d1">http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html</font></a></p>
		</div>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/60359.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-07-27 15:19 <a href="http://www.blogjava.net/wuxufeng8080/articles/60359.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>