分散式交易JTA實現Atomikos與Spring整合實踐

來源:互聯網
上載者:User

標籤:jta   atomikos   分散式交易   

  理解分散式交易JTA原理參見:http://www.ibm.com/developerworks/cn/java/j-lo-jta/

  JTA實現產品介紹:http://blog.chinaunix.net/uid-122937-id-3793220.html


  Atomikos官網無法訪問,不過Maven中央庫中具atomikos包。Atomikos整合Spring,Hibernate,Mybatis網上文章比較多,本文是通過JavaSE的方式借用Spring配置來測試Atomikos對JTA的實現。


 下面做一件事,就是兩(+)個資料庫,在一個事務裡對其分別對資料庫操作驗證操作的原子性,即要麼兩個資料庫的操作都成功,要麼都失敗。


 1.準備工作

  1.1 Maven pom.xml中添加依賴包

  atomikos:(目前最新版)

  

<dependency><groupId>com.atomikos</groupId><artifactId>transactions-jdbc</artifactId><version>3.9.3</version></dependency>


 jar依賴圖:

 650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/6D/ED/wKiom1Vu-WuiaLnzAACxcXC9yhs625.jpg" title="atomikos-transactions.png" alt="wKiom1Vu-WuiaLnzAACxcXC9yhs625.jpg" />

 

 Postgresql資料庫驅動:

<dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><version>9.2-1004-jdbc4</version></dependency>

 

 Spring,Junit依賴這裡省略。


 1.2 建立資料庫以及表

   資料庫分別是:javaee,tomdb

   650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/6D/E8/wKioL1Vu-8eAXWY-AADUZDXsd7M684.jpg" title="jta-temp.png" alt="wKioL1Vu-8eAXWY-AADUZDXsd7M684.jpg" />


 2.在項目中添加設定檔

  spring-jta.xml 和transaction.properties檔案,spring-jta.xml在src/main/resources/integration下,transaction.properties在src/main/resources/下。


 2.1在spring-jta.xml中配置兩個XADataSource:

 

<!-- 使用分散式交易時設定Postgresql的max_prepared_transactions為大於0的值,該值預設是0 --><!-- 資料庫A --><bean id="a" class="com.atomikos.jdbc.AtomikosDataSourceBean"init-method="init" destroy-method="close"><property name="uniqueResourceName" value="pg/a" /><property name="xaDataSourceClassName" value="org.postgresql.xa.PGXADataSource" /><property name="xaProperties"><props><prop key="user">postgres</prop><prop key="password">postgres</prop><prop key="serverName">localhost</prop><prop key="portNumber">5432</prop><prop key="databaseName">tomdb</prop></props></property><property name="poolSize" value="10" /><property name="reapTimeout" value="20000" /></bean><bean id="b" class="com.atomikos.jdbc.AtomikosDataSourceBean"init-method="init" destroy-method="close"><property name="uniqueResourceName" value="pg/b" /><property name="xaDataSourceClassName" value="org.postgresql.xa.PGXADataSource" /><property name="xaProperties"><props><prop key="user">postgres</prop><prop key="password">postgres</prop><prop key="serverName">localhost</prop><prop key="portNumber">5432</prop><prop key="databaseName">javaee</prop></props></property><property name="poolSize" value="10" /><property name="reapTimeout" value="20000" /></bean>


 說明:

 Postgresql的max_prepared_transactions參數值預設是0,要開啟分散式交易需要設定為大於0的值,該參數在PostgreSQL\9.3\data\postgresql.conf檔案中。

 PGXADataSource的父類BaseDataSource沒有url屬性,可需要分別設定serverName,portNumber,databaseName等屬性。不同的資料庫驅動有不同的實現方法。


 2.2 配置交易管理對象和UserTransaction介面實現

 

<!-- atomikos交易管理 --><bean id="atomikosUserTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"><description>UserTransactionManager</description><property name="forceShutdown" value="true" /></bean><bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"><property name="transactionTimeout" value="300" /></bean><bean id="transactionManager"class="org.springframework.transaction.jta.JtaTransactionManager"><property name="transactionManager" ref="atomikosUserTransactionManager"></property></bean>

 

 上面三個Bean可以獨立使用來進行事務控制,具體看下面3。


3. 編寫測試

 3.1 使用atomikosUserTransactionManager對象測試(TestAtomikos1.java)

 

package secondriver.springsubway.example.jta;import java.sql.Connection;import java.sql.SQLException;import javax.transaction.HeuristicMixedException;import javax.transaction.HeuristicRollbackException;import javax.transaction.NotSupportedException;import javax.transaction.RollbackException;import javax.transaction.SystemException;import org.junit.BeforeClass;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.atomikos.icatch.jta.UserTransactionManager;import com.atomikos.jdbc.AtomikosDataSourceBean;public class TestAtomikos1 {public static ApplicationContext ctx;@BeforeClasspublic static void beforeClass() {ctx = new ClassPathXmlApplicationContext("classpath:integration/spring-jta.xml");}public static void afterClass() {ctx = null;}@Testpublic void test1() {exe("abc", "abc");}@Testpublic void test2() {exe("123=", "123");}public void exe(String av, String bv) {AtomikosDataSourceBean adsA = (AtomikosDataSourceBean) ctx.getBean("a");AtomikosDataSourceBean adsB = (AtomikosDataSourceBean) ctx.getBean("b");Connection connA;Connection connB;UserTransactionManager utm = (UserTransactionManager) ctx.getBean("atomikosUserTransactionManager");try {utm.begin();connA = adsA.getConnection();connB = adsB.getConnection();connA.prepareStatement("insert into jta_temp (value) values(‘" + av + "‘)").execute();connB.prepareStatement("insert into jta_temp (value) values(‘" + bv + "‘)").execute();utm.commit();} catch (SQLException | NotSupportedException | SystemException| SecurityException | IllegalStateException | RollbackException| HeuristicMixedException | HeuristicRollbackException e) {e.printStackTrace();}}}


3.2使用Spring的JtaUserTransactionManager對象測試(TestAtomikos2.java 修改TestAtomikos1.java中的exe方法即可)

 

@Testpublic void test1() {exe("abc", "abc");}@Testpublic void test2() {exe("123=", "123");}
public void exe(String av, String bv) {TransactionFactory txm = (TransactionFactory) ctx.getBean("transactionManager");JdbcTemplate a = (JdbcTemplate) ctx.getBean("jdbcTemplateA");JdbcTemplate b = (JdbcTemplate) ctx.getBean("jdbcTemplateB");try {Transaction tx = txm.createTransaction("tx-name-define", 10000);a.update("insert into jta_temp (value) values(‘" + av + "‘)");b.update("insert into jta_temp (value) values(‘" + bv + "‘)");tx.commit();} catch (NotSupportedException | SystemException | SecurityException| RollbackException | HeuristicMixedException| HeuristicRollbackException e) {e.printStackTrace();}}

 

3.3使用atomikosUserTransaction Bean對象進行測試(TestAtomikos3.java 修改TestAtomikos1.java中的exe方法即可)

@Testpublic void test1() {exe("abc", "abc");}@Testpublic void test2() {exe("123", "123=");}


public void exe(String av, String bv) {AtomikosDataSourceBean adsA = (AtomikosDataSourceBean) ctx.getBean("a");AtomikosDataSourceBean adsB = (AtomikosDataSourceBean) ctx.getBean("b");Connection connA;Connection connB;UserTransaction utx = (UserTransaction) ctx.getBean("atomikosUserTransaction");try {utx.begin();connA = adsA.getConnection();connB = adsB.getConnection();connA.prepareStatement("insert into jta_temp (value) values(‘" + av + "‘)").execute();connB.prepareStatement("insert into jta_temp (value) values(‘" + bv + "‘)").execute();utx.commit();} catch (SQLException | NotSupportedException | SystemException| SecurityException | IllegalStateException | RollbackException| HeuristicMixedException | HeuristicRollbackException e) {e.printStackTrace();}}


 使用上述三種UserTransaction進行測試,其中test1方法是成功執行,test2方法是執行失敗的(因為插入的值長度超過的欄位長度限制)。通過分析之後,如果分布式事物控制正確,那麼資料庫中寫入的值對於兩張不同的表而言,是沒有數字值被寫入的。:

 650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/6D/ED/wKiom1Vu_tiwRFwEAAHJhvqOEPQ597.jpg" title="db-value.png" alt="wKiom1Vu_tiwRFwEAAHJhvqOEPQ597.jpg" />


 在測試過程中,經過對比確實達到了分散式交易控制的效果。


 關於JTA原理文章開始提到的那篇文章,寫的很詳細和清晰,可以細細閱讀和理解。

本文出自 “野馬紅塵” 部落格,請務必保留此出處http://aiilive.blog.51cto.com/1925756/1658102

分散式交易JTA實現Atomikos與Spring整合實踐

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.