JTA Transactions

JTA : Java Transaction API

界定事务的方式与事务管理器的实现无关

允许分布式事务处理。

JTA transaction允许访问多个数据库,通常的DBMS transaction是不允许的。

JTA transaction不允许nested transaction。


JTS : Java Transaction Service

GlassFish提供了包含JTS的事务管理器实现。但用户不会直接调用JTS,而是调用JTA,由JTA来调用更低层的JTS。


distributed transaction 包含:

一个transaction manager 

事务管理器: 管理所有事务参与者之间的通信。

一个或多个resource manager 

资源管理器: 持久化数据存储。


JTA与JDBC

JTA事务可以有多个参与者,参与者可以是 : JDBC连接、JDO PersistenceManager对象、JMS队列、JMS主题、EJB、J2EE Connector Architecture规范的资源分配器。

JDBC事务只能有一个参与者 : 一个JDBC连接,不能多个数据库。

两种模式:自动提交(default)、手动提交。


javax.transaction.UserTransaction

JTA来处理事务用到的Java类

JTA Transactions_第1张图片


更新多个数据库

JavaEE容器会管理所有的EJB事务,除了Bean-Managed JDBC事务。?

JavaEE事务管理器允许在同一个事务中,更新多个数据库。

(1) 在同一个JavaEE容器中

JTA Transactions_第2张图片

其中,Bean-A负责begin,end,所有X、Y、Z的操作在同一个事务中。

(2)在不同的JavaEE容器中

JTA Transactions_第3张图片

也是在同一个事务中,由JavaEE事务管理器们保证这一点。


JDBC事务示例代码:

package test.xue.transaction;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * database : transaction
 * table : message(title)
 * table : balance(user, balance)
 */
public class JDBCTransaction {
	public static Connection getConnection() throws Throwable {
		Class.forName("com.mysql.jdbc.Driver");
		Connection conn = DriverManager.getConnection(
				"jdbc:mysql://127.0.0.1:3306/transaction", "root", "root");

		return conn;
	}

	public void autoCommit() throws Throwable {
		Connection conn = JDBCTransaction.getConnection();

		Statement stmt = conn.createStatement();

		// default autoCommit
		stmt.executeUpdate("insert into message values('hello world')");

		conn.close();
	}

	public void noAutoCommit() throws Throwable {
		Connection conn = JDBCTransaction.getConnection();
		conn.setAutoCommit(false);

		String user1 = "Lily", user2 = "Lucy";
		int count = 123;
		Statement stmt = conn.createStatement();
		try {
			// begin a transaction
			int updated = stmt
					.executeUpdate("update balance set balance=balance-"
							+ count + " where user='" + user1 + "'");
			if (updated == 0) {
				throw new SQLException(user1 + " not exists");
			}
			updated = stmt.executeUpdate("update balance set balance=balance+"
					+ count + " where user='" + user2 + "'");
			if (updated == 0) {
				throw new SQLException(user1 + " not exists");
			}

			conn.commit();
			// end the transaction
		} catch (Throwable e) {
			// when exception occurs, rollback all
			conn.rollback();
			e.printStackTrace();
		}

		conn.close();
	}

	public static void main(String[] args) throws Throwable {
		JDBCTransaction jdbc = new JDBCTransaction();
		jdbc.autoCommit();
		jdbc.noAutoCommit();
	}
}

JTA事务:

JDBC驱动: javax.sql. XADataSource, XAConnection, XAResource

XAConnection与Connection的区别为: XAConnection可以用在JTA事务中,且不支持自动提交。

package test.xue.transaction;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.XAConnection;
import javax.sql.XADataSource;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;

import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlXid;

public class JTATransaction {
	public XADataSource getDataSource() {
		MysqlXADataSource ds = new MysqlXADataSource();
		ds.setServerName("localhost");
		ds.setPortNumber(3306);
		ds.setDatabaseName("transaction");

		return ds;
	}

	public void testJTA() throws SQLException, XAException {
		XADataSource ds = getDataSource();
		XAConnection xaconn = ds.getXAConnection("root", "root");
		Connection conn = xaconn.getConnection();
		Statement stmt = conn.createStatement();

		XAResource res = xaconn.getXAResource(); // for mysql-connector-java-5.1.21-bin.jar, return xaconn itself
		MysqlXid xid = new MysqlXid(new byte[] { 11 }, new byte[] { 22 }, 99);
		res.start(xid, XAResource.TMNOFLAGS);
		stmt.executeUpdate("insert into message values('hello JTA')");
		res.end(xid, XAResource.TMSUCCESS);
		int ret = res.prepare(xid);
		if (ret == XAResource.XA_OK) {
			res.commit(xid, false);
		}

		stmt.close();
		conn.close();
		xaconn.close();
	}

	public static void main(String[] args) throws SQLException, XAException {
		JTATransaction jta = new JTATransaction();
		jta.testJTA();
	}
}

其中,Xid的两个参数分别为:全局事务Id,分支事务Id。

此例子中没有用到事务管理器与资源管理器,也没有用到分布式事务和多个数据库,只是最简单的介绍JTA事务。

关于两阶段提交协议,以后再说吧。


Link : http://walsh.iteye.com/blog/258002


你可能感兴趣的:(JTA Transactions)