Atomikos TransactionsEssentials で JTA (Spring + JDBC 編)
TransactionsEssentials は、Atomikos のフリーの JTA 実装です。
とりあえずインストールしてみた。
サイトからダウンロードして、dist フォルダから必要な jar ファイルを選び、クラスパスに通します。
とりあえず、以下の jar があれば、最低限の JDBC 操作は行えます。
SpringFramework で適当に定義してみた。
beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" > <!-- ひとつめのデータソース --> <bean id="dataSource1" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <property name="uniqueResourceName" value="dataSource1" /> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /> <property name="xaProperties"> <props> <prop key="user">root</prop> <prop key="password"></prop> <prop key="url">jdbc:mysql://localhost:3307/test</prop> </props> </property> </bean> <!-- ふたつめのデータソース --> <bean id="dataSource2" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <property name="uniqueResourceName" value="dataSource2" /> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /> <property name="xaProperties"> <props> <prop key="user">root</prop> <prop key="password"></prop> <prop key="url">jdbc:mysql://localhost:3308/test</prop> </props> </property> </bean> <!-- Atomikos の TransactionManager 実装 --> <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <property name="forceShutdown" value="true" /> </bean> </beans>
commit してみた。
JdbcExample1.java
package sample; import java.sql.Connection; import java.sql.Statement; import javax.sql.DataSource; import javax.transaction.TransactionManager; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Sample for Atomikos TransactionsEssentials. * * @author beyondseeker@users.sourceforge.jp * @version $Id$ */ public class JdbcExample1 { public static void main(String[] args) throws Exception { // Create application context. ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // Prepare for using DataSource dataSource1 = (DataSource) ctx.getBean("dataSource1"); DataSource dataSource2 = (DataSource) ctx.getBean("dataSource2"); TransactionManager tm = (TransactionManager) ctx.getBean("atomikosTransactionManager"); // JDBC Example for XA Commit. tm.begin(); Connection connection1 = dataSource1.getConnection(); Statement st1 = connection1.createStatement(); st1.executeUpdate("insert into a () values ()"); Connection connection2 = dataSource2.getConnection(); Statement st2 = connection2.createStatement(); st2.executeUpdate("insert into a () values ()"); tm.commit(); } }
dataSource1 のログ
Query XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d Query insert into a () values () Query XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d Query XA PREPARE 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d Query XA COMMIT 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
dataSource2 のログ
Query XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d Query insert into a () values () Query XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d Query XA PREPARE 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d Query XA COMMIT 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d
ちゃんと2フェーズコミットできてますね。 (`・ω・´)
rollback してみた。
JdbcExample2.java
package sample; import java.sql.Connection; import java.sql.Statement; import javax.sql.DataSource; import javax.transaction.TransactionManager; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Sample for Atomikos TransactionsEssentials. * * @author beyondseeker@users.sourceforge.jp * @version $Id$ */ public class JdbcExample2 { public static void main(String[] args) throws Exception { // Create application context. ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // Prepare for using DataSource dataSource1 = (DataSource) ctx.getBean("dataSource1"); DataSource dataSource2 = (DataSource) ctx.getBean("dataSource2"); TransactionManager tm = (TransactionManager) ctx.getBean("atomikosTransactionManager"); // JDBC Example for XA Rollback. tm.begin(); Connection connection1 = dataSource1.getConnection(); Statement st1 = connection1.createStatement(); st1.executeUpdate("insert into a () values ()"); Connection connection2 = dataSource2.getConnection(); Statement st2 = connection2.createStatement(); st2.executeUpdate("insert into a () values ()"); tm.rollback(); } }
dataSource1 のログ
Query XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d Query insert into a () values () Query XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d Query XA ROLLBACK 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
dataSource2 のログ
Query XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d Query insert into a () values () Query XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d Query XA ROLLBACK 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d
ちゃんとロールバックできてますね。 (`・ω・´)