atomikos jta 分布式事务(多数据源)处理

2019年12月05日 阅读数:53
这篇文章主要向大家介绍atomikos jta 分布式事务(多数据源)处理,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

1.一、事务的定义:

事务是指多个操做单元组成的合集,多个单元操做是总体不可分割的,要么都操做不成功,要么都成功。其必须遵循四个原则(ACID)php

1.二、事务四个原则(ACID)

一、原子性(Atomicity):即事务是不可分割的最小工做单元,事务内的操做要么全作,要么全不作;html

二、一致性(Consistency):在事务执行前数据库的数据处于正确的状态,而事务执行完成后数据库的数据仍是应该处于正确的状态,即数据完整性约束没有被破坏;如银行转账,A转账给B,必须保证A的钱必定转给B,必定不会出现A的钱转了但B没收到,不然数据库的数据就处于不一致(不正确)的状态。java

三、隔离性(Isolation):并发事务执行之间互不影响,在一个事务内部的操做对其余事务是不产生影响,这须要事务隔离级别来指定隔离性;node

四、持久性(Durability):事务一旦执行成功,它对数据库的数据的改变必须是永久的,不会因好比遇到系统故障或断电形成数据不一致或丢失。mysql

1.三、隔离级别(isolation level)

隔离级别定义了事务与事务之间的隔离程度、隔离级别与并发性是互为矛盾的:隔离程度越高,数据库的并发性越差;隔离程度越低,数据库的并发性越好。web

1.四、事务隔离级别并发现象

一、更新丢失(lost update):spring

    当系统容许两个事务同时更新同一数据时,发生更新丢失。sql

         A事务读取User表中的id为1的记录(id=1,name=zhansan,age=20)数据库

         B事务读取User表中的id为1的记录(id=1,name=zhansan,age=20)apache

         A事务将id为1的记录的name修改成lisi,提交事务

         B事务将id为1的记录的age修改22,提交事务

则A事务就会出现更新丢失

 

二、脏读(dirty read)

          当一个事务读取另外一个事务还没有提交的修改时,产生脏读。

         A事务读取User表中的id为1的记录(id=1,name=zhansan,age=20)

         A事务将id为1的记录的name修改成lisi(id=1, name=lisi,age=20)

         B事务读取User表中的id为1的记录(id=1, name=lisi,age=20)

         此时A事务撤销更改,事务回滚(id=1,name=zhansan,age=20)

         因为A事务回滚了,数据库内不会有任何操做记录,那么B事务是什么时候、从哪里读取了错误数据根本无从查起。

 

三、非重复读(nonrepeatableread)

         同一查询在同一事务中屡次进行,在此期间,因为其余事务提交了对数据的修改或删除,每次返回不一样的结果。

         A事务读取某数据,这个数据已经被B事务读取,并作了修改或删除。因此这数据已经不是之前的数据。

 

四、幻像(phantom read)

          同一查询在同一事务中屡次进行,因为其余提交事务所作的插入操做,虽然查询条件相同,每次返回的结果集却不一样。

     A事务重复持行一个查询,因为其余提交事务所作的插入操做,返回不一样的结果集,此时发生幻像读。

 

1.五、隔离级别和对应现象的空值状况

隔离级别

脏读

非重复读

幻读

未提交读

Y

Y

Y

提交读

N

Y

Y

可重复读

N

N

Y

序列化

N

N

N

 

1.六、数据库事务分为本地事务跟全局事务

本地事务:普通事务,独立一个数据库,能保证在该数据库上操做的ACID。

分布式事务:涉及两个或多个数据库源的事务,即跨越多台同类或异类数据库的事务(由每台数据库的本地事务组成的),分布式事务旨在保证这些本地事务的全部操做的ACID,使事务能够跨越多台数据库;

1.七、Java事务类型分为JDBC事务跟JTA事务

JDBC事务:即为上面说的数据库事务中的本地事务,经过connection对象控制管理。

JTA事务:JTA指Java事务API(JavaTransaction API),是Java EE数据库事务规范, JTA只提供了事务管理接口,由应用程序服务器厂商(如WebSphere Application Server)提供实现,JTA事务比JDBC更强大,支持分布式事务。

1.八、Spring事务传播行为:有七大传播行为,也是在TransactionDefinition接口中定义。

PROPAGATION_REQUIRED:支持当前事务,如当前没有事务,则新建一个。

PROPAGATION_SUPPORTS:支持当前事务,如当前没有事务,则已非事务性执行(源码中提示有个注意点,看不太明白,留待后面考究)。

PROPAGATION_MANDATORY:支持当前事务,如当前没有事务,则抛出异常(强制必定要在一个已经存在的事务中执行,业务方法不可独自发起本身的事务)。

PROPAGATION_REQUIRES_NEW:始终新建一个事务,如当前原来有事务,则把原事务挂起。

PROPAGATION_NOT_SUPPORTED:不支持当前事务,始终已非事务性方式执行,如当前事务存在,挂起该事务。

PROPAGATION_NEVER:不支持当前事务;若是当前事务存在,则引起异常。

PROPAGATION_NESTED:若是当前事务存在,则在嵌套事务中执行,若是当前没有事务,则执行与 PROPAGATION_REQUIRED 相似的操做(注意:当应用到JDBC时,只适用JDBC 3.0以上驱动)。

1.九、Spring多数据源分布式事务spring+atomikos[jta]+druid+mybatis

spring3.0以后再也不支持jtom[jta]了,第三方开源软件atomikos(http://www.atomikos.com/)来实现.

atomikos事务控制框架,其中看到有3种数据源,分别是,SimpleDataSourceBean,AtomikosDataSourceBean,AtomikosNonXADataSourceBean。

  a:SimpleDataSourceBean: 这个是最简单地数据源配置,须要配置XA驱动。

  b:AtomikosDataSourceBean:  分布式数据源,Atomikos实现的数据源,须要配置XA驱动,推荐此配置,能够配置链接池的信息。

  c:AtomikosNonXADataSourceBean: 非分布式数据源,该数据源配置须要普通JDBC的驱动,能够配置链接池:

  Atomikos支持XA(全局事务)和NON-XA(非全局事务),NON-XA[nonxadatasource]效率高于XA.XA事务每每是包括多个数据源的全局事务,非XA是单个数据源的.

   XA链接是一个JTA事务中的参与者。XA链接不支持JDBC的自动提交特性。也就是说应用程序没必要在xadatasource[XA]链接上调用Java.sql.Connection.commit()或java.sql.Connection.rollback();而应用程序应该使用UserTransaction.begin(),UserTransaction.commit()和UserTransaction.rollback().


一、  建立两个数据库

1.一、建立第一个数据库multi-db1


   
   
   
  1. CREATE DATABASE `multi-db1` DEFAULT CHARACTER SET utf8;
  2. USE `multi-db1`;
  3. DROP TABLE IF EXISTS `t_user`;
  4. CREATE TABLE `t_user` (
  5. `id` varchar( 100) DEFAULT NULL,
  6. `name` varchar( 200) DEFAULT NULL,
  7. `gender` varchar( 2) DEFAULT NULL,
  8. `birthday` datetime DEFAULT NULL
  9. ) ENGINE= InnoDB DEFAULT CHARSET=utf8;

1.二、建立第二个数据库multi-db2


   
   
   
  1. CREATE DATABASE `multi-db2` DEFAULT CHARACTER SET utf8;
  2. USE `multi-db2`;
  3. DROP TABLE IF EXISTS `t_user`;
  4. CREATE TABLE `t_user` (
  5. `id` varchar( 100) DEFAULT NULL,
  6. `name` varchar( 200) DEFAULT NULL,
  7. `gender` varchar( 2) DEFAULT NULL,
  8. `birthday` datetime DEFAULT NULL
  9. ) ENGINE= InnoDB DEFAULT CHARSET=utf8;
二、  建立一个maven的项目类型为jar项目目录为


三、项目的POM文件pom.xml

   
   
   
  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0 </modelVersion>
  4. <groupId>com.jyd.transaction </groupId>
  5. <artifactId>DTransaction </artifactId>
  6. <version>0.0.1-SNAPSHOT </version>
  7. <dependencies>
  8. <dependency>
  9. <groupId>org.springframework </groupId>
  10. <artifactId>spring-context </artifactId>
  11. <version>4.2.5.RELEASE </version>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.springframework </groupId>
  15. <artifactId>spring-test </artifactId>
  16. <version>4.2.5.RELEASE </version>
  17. </dependency>
  18. <dependency>
  19. <groupId>com.alibaba </groupId>
  20. <artifactId>druid </artifactId>
  21. <version>1.0.26 </version>
  22. </dependency>
  23. <dependency>
  24. <groupId>mysql </groupId>
  25. <artifactId>mysql-connector-java </artifactId>
  26. <version>5.1.36 </version>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.slf4j </groupId>
  30. <artifactId>slf4j-api </artifactId>
  31. <version>1.7.12 </version>
  32. </dependency>
  33. <dependency>
  34. <groupId>junit </groupId>
  35. <artifactId>junit </artifactId>
  36. <version>4.10 </version>
  37. </dependency>
  38. <!-- transaction -->
  39. <dependency>
  40. <groupId>org.springframework </groupId>
  41. <artifactId>spring-tx </artifactId>
  42. <version>4.2.5.RELEASE </version>
  43. </dependency>
  44. <dependency>
  45. <groupId>javax.transaction </groupId>
  46. <artifactId>jta </artifactId>
  47. <version>1.1 </version>
  48. </dependency>
  49. <dependency>
  50. <groupId>com.atomikos </groupId>
  51. <artifactId>atomikos-util </artifactId>
  52. <version>4.0.2 </version>
  53. </dependency>
  54. <dependency>
  55. <groupId>com.atomikos </groupId>
  56. <artifactId>transactions </artifactId>
  57. <version>4.0.2 </version>
  58. </dependency>
  59. <dependency>
  60. <groupId>com.atomikos </groupId>
  61. <artifactId>transactions-jta </artifactId>
  62. <version>4.0.2 </version>
  63. </dependency>
  64. <dependency>
  65. <groupId>com.atomikos </groupId>
  66. <artifactId>transactions-jdbc </artifactId>
  67. <version>4.0.2 </version>
  68. </dependency>
  69. <dependency>
  70. <groupId>com.atomikos </groupId>
  71. <artifactId>transactions-api </artifactId>
  72. <version>4.0.2 </version>
  73. </dependency>
  74. <dependency>
  75. <groupId>cglib </groupId>
  76. <artifactId>cglib-nodep </artifactId>
  77. <version>3.2.2 </version>
  78. </dependency>
  79. <dependency>
  80. <groupId>org.aspectj </groupId>
  81. <artifactId>aspectjrt </artifactId>
  82. <version>1.8.0 </version>
  83. </dependency>
  84. <dependency>
  85. <groupId>org.aspectj </groupId>
  86. <artifactId>aspectjweaver </artifactId>
  87. <version>1.8.0 </version>
  88. </dependency>
  89. <dependency>
  90. <groupId>org.mybatis </groupId>
  91. <artifactId>mybatis-spring </artifactId>
  92. <version>1.3.0 </version>
  93. </dependency>
  94. <dependency>
  95. <groupId>org.mybatis </groupId>
  96. <artifactId>mybatis </artifactId>
  97. <version>3.4.0 </version>
  98. </dependency>
  99. <dependency>
  100. <groupId>org.springframework </groupId>
  101. <artifactId>spring-jdbc </artifactId>
  102. <version>4.2.5.RELEASE </version>
  103. </dependency>
  104. </dependencies>
  105. <build>
  106. <plugins>
  107. <!-- 资源文件拷贝插件 -->
  108. <plugin>
  109. <groupId>org.apache.maven.plugins </groupId>
  110. <artifactId>maven-resources-plugin </artifactId>
  111. <version>2.7 </version>
  112. <configuration>
  113. <encoding>UTF-8 </encoding>
  114. </configuration>
  115. </plugin>
  116. <plugin>
  117. <groupId>org.apache.maven.plugins </groupId>
  118. <artifactId>maven-compiler-plugin </artifactId>
  119. <configuration>
  120. <source>1.6 </source>
  121. <target>1.6 </target>
  122. <encoding>UTF-8 </encoding>
  123. </configuration>
  124. </plugin>
  125. </plugins>
  126. </build>
  127. </project>
四、配置数据源参数db.properties

   
   
   
  1. #mysql-Used to verify the effectiveness of the database connection
  2. validationQuery=SELECT 1
  3. jdbc.initialSize= 5
  4. jdbc.maxActive= 20
  5. jdbc.maxWait= 60000
  6. jdbc.poolPreparedStatements= false
  7. jdbc.poolMaximumIdleConnections= 0
  8. jdbc.driverClassName=com.mysql.jdbc.Driver
  9. jdbc.xaDataSourceClassName=com.alibaba.druid.pool.xa.DruidXADataSource
  10. #jdbc.xaDataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
  11. # 1.tms business. 2.The db level optimization,data concurrency,desirable.
  12. master.jdbc.url=jdbc:mysql: //localhost:3306/multi-db1?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
  13. slave.jdbc.url=jdbc:mysql: //localhost:3306/multi-db2?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
  14. jdbc.username=root
  15. jdbc.password= 123456
五、AtomikosDataSourceBean[XA(全局事务)]数据源配置datasource-context.xml

   
   
   
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:context= "http://www.springframework.org/schema/context"
  4. xmlns:mvc= "http://www.springframework.org/schema/mvc" xmlns:tx= "http://www.springframework.org/schema/tx"
  5. xmlns:aop= "http://www.springframework.org/schema/aop"
  6. xsi:schemaLocation= "http://www.springframework.org/schema/mvc
  7. http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
  8. http://www.springframework.org/schema/beans
  9. http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  10. http://www.springframework.org/schema/context
  11. http://www.springframework.org/schema/context/spring-context-4.0.xsd
  12. http://www.springframework.org/schema/tx
  13. http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
  14. http://www.springframework.org/schema/aop
  15. http://www.springframework.org/schema/aop/spring-aop-4.0.xsd" default-lazy-init= "true">
  16. <description>配置DB1-DB2数据源信息 </description>
  17. <!-- com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean -->
  18. <bean id="abstractXADataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" abstract="true">
  19. <property name="xaDataSourceClassName" value="${jdbc.xaDataSourceClassName}"</span>/&gt;</span> <span class="hljs-comment">&lt;!-- SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase, Hana] --&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="20"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"poolSize"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"10"</span> /&gt;</span> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="21"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"minPoolSize"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"10"</span>/&gt;</span> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="22"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"maxPoolSize"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"30"</span>/&gt;</span> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="23"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"borrowConnectionTimeout"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"60"</span>/&gt;</span> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="24"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"reapTimeout"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"20"</span>/&gt;</span> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="25"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"maxIdleTime"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"60"</span>/&gt;</span> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="26"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"maintenanceInterval"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"60"</span>/&gt;</span> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="27"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"loginTimeout"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"60"</span>/&gt;</span> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="28"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"testQuery"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"${validationQuery}"/>
  20. </bean>
  21. <bean id="db1DataSource" parent="abstractXADataSource">
  22. <property name="uniqueResourceName" value="DB1" />
  23. <property name="xaProperties">
  24. <props>
  25. <prop key="driverClassName">${jdbc.driverClassName}<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="35"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"url"</span>&gt;</span>${master.jdbc.url} </prop>
  26. <prop key="password">${jdbc.password}<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="37"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">&lt;!-- &lt;prop key="user"&gt;${jdbc.username}</prop> --> <!-- mysql -->
  27. <prop key="username">${jdbc.username}<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span> <span class="hljs-comment">&lt;!-- durid --&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="39"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"initialSize"</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="40"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"maxActive"</span>&gt;</span>20<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span> <span class="hljs-comment">&lt;!-- 若不配置则代码执行"{dataSource-1} inited"此处中止 --&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="41"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"minIdle"</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="42"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"maxWait"</span>&gt;</span>60000<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="43"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"validationQuery"</span>&gt;</span>${validationQuery} </prop>
  28. <prop key="testOnBorrow">false </prop>
  29. <prop key="testOnReturn">false </prop>
  30. <prop key="testWhileIdle">true </prop>
  31. <prop key="removeAbandoned">true </prop>
  32. <prop key="removeAbandonedTimeout">1800 </prop>
  33. <prop key="logAbandoned">true </prop>
  34. <prop key="filters">mergeStat </prop>
  35. </props>
  36. </property>
  37. </bean>
  38. <bean id="db2DataSource" parent="abstractXADataSource">
  39. <property name="uniqueResourceName" value="DB2" />
  40. <property name="xaProperties">
  41. <props>
  42. <prop key="driverClassName">${jdbc.driverClassName}<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="59"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"url"</span>&gt;</span>${slave.jdbc.url} </prop>
  43. <prop key="password">${jdbc.password}<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="61"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">&lt;!-- &lt;prop key="user"&gt;${jdbc.username}</prop> -->
  44. <prop key="username">${jdbc.username}<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="63"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"initialSize"</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="64"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"maxActive"</span>&gt;</span>20<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="65"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"minIdle"</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="66"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"maxWait"</span>&gt;</span>60000<span class="hljs-tag">&lt;/<span class="hljs-name">prop</span>&gt;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="67"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-tag">&lt;<span class="hljs-name">prop</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"validationQuery"</span>&gt;</span>${validationQuery} </prop>
  45. <prop key="testOnBorrow">false </prop>
  46. <prop key="testOnReturn">false </prop>
  47. <prop key="testWhileIdle">true </prop>
  48. <prop key="removeAbandoned">true </prop>
  49. <prop key="removeAbandonedTimeout">1800 </prop>
  50. <prop key="logAbandoned">true </prop>
  51. <prop key="filters">mergeStat </prop>
  52. </props>
  53. </property>
  54. </bean>
  55. </beans>
六、配置mybatis-config

         mybatis-config-db1.xml


   
   
   
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
  3. <configuration>
  4. <typeAliases>
  5. <typeAlias alias="User" type="com.jyd.entity.User"/>
  6. </typeAliases>
  7. <mappers>
  8. <mapper resource="com/jyd/xml/UserMapper.xml" />
  9. </mappers>
  10. </configuration>

mybatis-config-db2.xml


   
   
   
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
  3. <configuration>
  4. <typeAliases>
  5. <typeAlias alias="UserInfo" type="com.jyd.entity.UserInfo"/>
  6. </typeAliases>
  7. <mappers>
  8. <mapper resource="com/jyd/xml/UserInfoMapper.xml" />
  9. </mappers>
  10. </configuration>
七、mybatis的配置mybatis-context.xml

   
   
   
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context= "http://www.springframework.org/schema/context"
  5. xmlns:mvc= "http://www.springframework.org/schema/mvc"
  6. xmlns:tx= "http://www.springframework.org/schema/tx"
  7. xmlns:aop= "http://www.springframework.org/schema/aop"
  8. xsi:schemaLocation= "http://www.springframework.org/schema/mvc
  9. http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
  10. http://www.springframework.org/schema/beans
  11. http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  12. http://www.springframework.org/schema/context
  13. http://www.springframework.org/schema/context/spring-context-4.0.xsd
  14. http://www.springframework.org/schema/tx
  15. http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
  16. http://www.springframework.org/schema/aop
  17. http://www.springframework.org/schema/aop/spring-aop-4.0.xsd" default-lazy-init= "true">
  18. <bean id="db1SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  19. <property name="configLocation" value="classpath:mybatis/mybatis-config-db1.xml" />
  20. <property name="dataSource" ref="db1DataSource" />
  21. </bean>
  22. <bean id="db2SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  23. <property name="configLocation" value="classpath:mybatis/mybatis-config-db2.xml" />
  24. <property name="dataSource" ref="db2DataSource" />
  25. </bean>
  26. </beans>
八、Mapper的管理及注入,为mybatis的dao层mapper接口注入[绑定]sqlSessionFactory

   
   
   
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context= "http://www.springframework.org/schema/context"
  5. xmlns:mvc= "http://www.springframework.org/schema/mvc"
  6. xmlns:tx= "http://www.springframework.org/schema/tx"
  7. xmlns:aop= "http://www.springframework.org/schema/aop"
  8. xsi:schemaLocation= "http://www.springframework.org/schema/mvc
  9. http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
  10. http://www.springframework.org/schema/beans
  11. http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  12. http://www.springframework.org/schema/context
  13. http://www.springframework.org/schema/context/spring-context-4.0.xsd
  14. http://www.springframework.org/schema/tx
  15. http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
  16. http://www.springframework.org/schema/aop
  17. http://www.springframework.org/schema/aop/spring-aop-4.0.xsd" default-lazy-init= "true">
  18. <description>MyBatis为不一样的mapper注入sqlSessionFactory </description>
  19. <!-- Mapper的管理及注入 -->
  20. <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  21. <property name="sqlSessionFactory" ref="db1SqlSessionFactory" />
  22. <property name="mapperInterface" value="com.jyd.dao.UserMapper" />
  23. </bean>
  24. <bean id="userInfoMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  25. <property name="sqlSessionFactory" ref="db2SqlSessionFactory" />
  26. <property name="mapperInterface" value="com.jyd.dao.UserInfoMapper" />
  27. </bean>
  28. </beans>
九、atomikos事务配置transaction-context.xml

   
   
   
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:context= "http://www.springframework.org/schema/context"
  4. xmlns:mvc= "http://www.springframework.org/schema/mvc" xmlns:tx= "http://www.springframework.org/schema/tx"
  5. xmlns:aop= "http://www.springframework.org/schema/aop"
  6. xsi:schemaLocation= "http://www.springframework.org/schema/mvc
  7. http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
  8. http://www.springframework.org/schema/beans
  9. http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  10. http://www.springframework.org/schema/context
  11. http://www.springframework.org/schema/context/spring-context-4.0.xsd
  12. http://www.springframework.org/schema/tx
  13. http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
  14. http://www.springframework.org/schema/aop
  15. http://www.springframework.org/schema/aop/spring-aop-4.0.xsd" default-lazy-init= "true">
  16. <description>配置事物 </description>
  17. <!-- atomikos事务管理器 -->
  18. <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
  19. <property name="forceShutdown">
  20. <value>true </value>
  21. </property>
  22. </bean>
  23. <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
  24. <property name="transactionTimeout" value="300" />
  25. </bean>
  26. <!-- spring 事务管理器 -->
  27. <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
  28. <property name="transactionManager" ref="atomikosTransactionManager" />
  29. <property name="userTransaction" ref="atomikosUserTransaction" />
  30. <!-- 必须设置,不然程序出现异常 JtaTransactionManager does not support custom isolation levels by default -->
  31. <property name="allowCustomIsolationLevels" value="true"/>
  32. </bean>
  33. <aop:config proxy-target-class="true">
  34. <aop:advisor pointcut="(execution(* com.jyd.service.*.* (..)))" advice-ref="txAdvice" />
  35. </aop:config>
  36. <tx:advice id="txAdvice" transaction-manager="springTransactionManager">
  37. <tx:attributes>
  38. <tx:method name="get*" propagation="REQUIRED" read-only="true" />
  39. <tx:method name="find*" propagation="REQUIRED" read-only="true" />
  40. <tx:method name="has*" propagation="REQUIRED" read-only="true" />
  41. <tx:method name="locate*" propagation="REQUIRED" read-only="true" />
  42. <tx:method name="register*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
  43. </tx:attributes>
  44. </tx:advice>
  45. </beans>
十、配置jta启动参数在jta.properties,最后追加详细

   
   
   
  1. com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
  2. com.atomikos.icatch.console_file_name = /home/logs/tx/tx.out.log
  3. com.atomikos.icatch.log_base_name = txlog
  4. com.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tm
  5. com.atomikos.icatch.console_log_level=DEBUG
十一、spring主配置文件spring-context.xml


   
   
   
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:p= "http://www.springframework.org/schema/p"
  4. xmlns:context= "http://www.springframework.org/schema/context"
  5. xmlns:aop= "http://www.springframework.org/schema/aop"
  6. xmlns:mvc= "http://www.springframework.org/schema/mvc"
  7. xsi:schemaLocation= "http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  9. http://www.springframework.org/schema/context
  10. http://www.springframework.org/schema/context/spring-context-3.2.xsd
  11. http://www.springframework.org/schema/aop
  12. http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
  13. http://www.springframework.org/schema/mvc
  14. http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
  15. <!-- 使用annotation 自动注册bean,并检查@Required,@Autowired的属性已被注入 -->
  16. <context:component-scan base-package="com.jyd" />
  17. <!-- 使用AspectJ方式配置AOP -->
  18. <aop:aspectj-autoproxy />
  19. <!-- 引入属性配置文件 -->
  20. <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  21. <property name="location" value="classpath:properties/db.properties" />
  22. </bean>
  23. <!--或 <context:property-placeholder location="classpath*:*.properties" /> -->
  24. <import resource="datasource-context.xml"/>
  25. <import resource="mapper-context.xml"/>
  26. <import resource="mybatis-context.xml"/>
  27. <import resource="transaction-context.xml"/>
  28. </beans>
十二、建立实体bean类(User.java|UserInfo.java)

User.java


   
   
   
  1. package com.jyd.entity;
  2. import java.io.Serializable;
  3. import java.util.Date;
  4. public class User implements Serializable {
  5. private static final long serialVersionUID = - 5650864083291329775L;
  6. private String id;
  7. private String name;
  8. private String gender;
  9. private Date birthday;
  10. public String getId() {
  11. return id;
  12. }
  13. public void setId(String id) {
  14. this.id = id;
  15. }
  16. public String getName() {
  17. return name;
  18. }
  19. public void setName(String name) {
  20. this.name = name;
  21. }
  22. public String getGender() {
  23. return gender;
  24. }
  25. public void setGender(String gender) {
  26. this.gender = gender;
  27. }
  28. public Date getBirthday() {
  29. return birthday;
  30. }
  31. public void setBirthday(Date birthday) {
  32. this.birthday = birthday;
  33. }
  34. }

UserInfo.java


   
   
   
  1. package com.jyd.entity;
  2. import java.io.Serializable;
  3. import java.util.Date;
  4. public class UserInfo implements Serializable {
  5. private static final long serialVersionUID = 7402046259459506152L;
  6. private String id;
  7. private String name;
  8. private String gender;
  9. private Date birthday;
  10. public String getId() {
  11. return id;
  12. }
  13. public void setId(String id) {
  14. this.id = id;
  15. }
  16. public String getName() {
  17. return name;
  18. }
  19. public void setName(String name) {
  20. this.name = name;
  21. }
  22. public String getGender() {
  23. return gender;
  24. }
  25. public void setGender(String gender) {
  26. this.gender = gender;
  27. }
  28. public Date getBirthday() {
  29. return birthday;
  30. }
  31. public void setBirthday(Date birthday) {
  32. this.birthday = birthday;
  33. }
  34. }
1三、建立mybatis的mapper和dao接口(UserMapper.java|UserInfoMapper.java)和对应mapper文件

UserMapper.java


   
   
   
  1. package com.jyd.dao;
  2. import org.springframework.stereotype.Repository;
  3. import com.jyd.entity.User;
  4. @Repository
  5. public interface UserMapper {
  6. int insert(User record);
  7. }

UserInfoMapper.java


   
   
   
  1. package com.jyd.dao;
  2. import org.springframework.stereotype.Repository;
  3. import com.jyd.entity.UserInfo;
  4. @Repository
  5. public interface UserInfoMapper {
  6. int insert(UserInfo record);
  7. }
UserMapper.xml

   
   
   
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3. <mapper namespace="com.jyd.dao.UserMapper" >
  4. <insert id="insert" parameterType="com.jyd.entity.User" >
  5. insert into t_user (id, name, gender, birthday)
  6. values (#{id}, #{name}, #{gender},#{birthday})
  7. </insert>
  8. </mapper>

UserInfoMapper.xml


   
   
   
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3. <mapper namespace="com.jyd.dao.UserInfoMapper" >
  4. <insert id="insert" parameterType="com.jyd.entity.UserInfo" >
  5. insert into t_user (id, name, gender, birthday)
  6. values (#{id}, #{name}, #{gender},#{birthday})
  7. </insert>
  8. </mapper>
1四、建立UserService服务层和实现(UserService.java|UserServiceImpl.java)

UserService.java


   
   
   
  1. package com.jyd.service;
  2. import com.jyd.entity.User;
  3. import com.jyd.entity.UserInfo;
  4. public interface UserService {
  5. boolean registerUser(User user, UserInfo userInfo);
  6. }

UserServiceImpl.java


   
   
   
  1. package com.jyd.service.impl;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Service;
  6. import com.jyd.dao.UserInfoMapper;
  7. import com.jyd.dao.UserMapper;
  8. import com.jyd.entity.User;
  9. import com.jyd.entity.UserInfo;
  10. import com.jyd.service.UserService;
  11. @Service( "userService")
  12. public class UserServiceImpl implements UserService {
  13. //log
  14. private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class);
  15. @Autowired
  16. private UserMapper userMapper;
  17. @Autowired
  18. private UserInfoMapper userInfoMapper;
  19. @Override
  20. public boolean registerUser(User user, UserInfo userInfo) {
  21. boolean resRegister = false;
  22. try {
  23. if(userMapper.insert(user) != 1){
  24. throw new RuntimeException( "注册用户:User表数据插入不一致.");
  25. }
  26. if(userInfoMapper.insert(userInfo) != 1){
  27. throw new RuntimeException( "注册用户:UserInfo表数据插入不一致.");
  28. }
  29. resRegister = true;
  30. } catch (Exception e) {
  31. LOG.info( "注册用户:数据库保存异常." + e.getMessage(), e);
  32. throw new RuntimeException( "注册用户:数据库保存异常");
  33. }
  34. return resRegister;
  35. }
  36. }
1五、Junit测试代码

   
   
   
  1. package com.jyd.test;
  2. import java.util.Calendar;
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.test.context.ContextConfiguration;
  9. import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
  10. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  11. import com.jyd.entity.User;
  12. import com.jyd.entity.UserInfo;
  13. import com.jyd.service.UserService;
  14. @RunWith(SpringJUnit4ClassRunner.class)
  15. @ContextConfiguration(locations = { "classpath:spring-context.xml"})
  16. public class JTATest extends AbstractJUnit4SpringContextTests{
  17. //log
  18. private static final Logger LOG = LoggerFactory.getLogger(JTATest.class);
  19. @Autowired
  20. private UserService userService;
  21. @Test
  22. public void testRegister(){
  23. User user = new User();
  24. user.setId( "1");
  25. user.setName( "张三");
  26. user.setGender( "男");
  27. user.setBirthday(Calendar.getInstance().getTime());
  28. UserInfo userInfo = new UserInfo();
  29. userInfo.setId( "1");
  30. userInfo.setName( "张三");
  31. userInfo.setGender( "男");
  32. userInfo.setBirthday(Calendar.getInstance().getTime());
  33. if(userService.registerUser(user, userInfo)){
  34. LOG.info( "##用户注册成功");
  35. } else{
  36. LOG.info( "##用户注册失败");
  37. }
  38. }
  39. }

能够作异常测试,其中如何方法出错了,都会回滚事务

            </div>