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类
更新多个数据库
JavaEE容器会管理所有的EJB事务,除了Bean-Managed JDBC事务。?
JavaEE事务管理器允许在同一个事务中,更新多个数据库。
(1) 在同一个JavaEE容器中
其中,Bean-A负责begin,end,所有X、Y、Z的操作在同一个事务中。
(2)在不同的JavaEE容器中
也是在同一个事务中,由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(); } }
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(); } }
此例子中没有用到事务管理器与资源管理器,也没有用到分布式事务和多个数据库,只是最简单的介绍JTA事务。
关于两阶段提交协议,以后再说吧。
Link : http://walsh.iteye.com/blog/258002