Spring分布式事务- 三种实现方式(Spring+JTA)
2016-01-15 17:38
453 查看
分布式事务是指事务的参与者、支持事务的服务器、资源管理器以及事务管理器分别位于分布系统的不同节点之上,在两个或多个网络计算机资源上访问并且更新数据,将两个或多个网络计算机的数据进行的多次操作作为一个整体进行处理。如不同银行账户之间的转账。
对于在项目中接触到JTA,大部分的原因是因为在项目中需要操作多个数据库,同时,可以保证操作的原子性,保证对多个数据库的操作一致性。
项目结构图
1、pom.xml
2、applicationContext.xml
3、java类
package com.roden.jta.controller;
数据源详细参数配置
对于在项目中接触到JTA,大部分的原因是因为在项目中需要操作多个数据库,同时,可以保证操作的原子性,保证对多个数据库的操作一致性。
项目结构图
1、pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <packaging>war</packaging> <name>jta</name> <groupId>com.roden.jta</groupId> <artifactId>jta</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <!-- 表示开发的时候引入,发布的时候不会加载此包 --> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>3.2.14.RELEASE</version> <scope>provided</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> </dependency> <dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-jdbc</artifactId> <version>3.9.3</version> </dependency> <dependency> <groupId>javax.transaction</groupId> <artifactId>jta</artifactId> <version>1.1</version> </dependency> <!-- javaee-api包含了JavaEE规范中的api,如servlet-api,persistence-api, transaction-api等 --> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>3.2.16.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>3.2.16.RELEASE</version> </dependency> </dependencies> </project>
2、applicationContext.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" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd" default-lazy-init="true"> <!-- mysql数据源 --> <bean id="master" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <description>master xa datasource</description> <property name="uniqueResourceName"> <value>master</value> </property> <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://127.0.0.1:3306/master</prop> </props> </property> <property name="poolSize" value="10"/> </bean> <bean id="slave" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <description>slave xa datasource</description> <property name="uniqueResourceName"> <value>slave</value> </property> <property name="xaDataSourceClassName"> <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value> </property> <property name="xaProperties"> <props> <prop key="user">root</prop> <prop key="password"></prop> <prop key="URL">jdbc:mysql://127.0.0.1:3306/slave</prop> </props> </property> <property name="poolSize" value="10"/> </bean> <!-- atomikos事务管理器 --> <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <description>UserTransactionManager</description> <property name="forceShutdown"> <value>true</value> </property> </bean> <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"> <property name="transactionTimeout" value="300" /> </bean> <!-- spring 事务管理器 --> <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager"> <ref bean="atomikosTransactionManager" /> </property> <property name="userTransaction"> <ref bean="atomikosUserTransaction" /> </property> </bean> <!-- spring 事务模板 --> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager"> <ref bean="springTransactionManager" /> </property> </bean> <bean id="masterJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg> <ref bean="master" /> </constructor-arg> </bean> <bean id="slaveJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg> <ref bean="slave" /> </constructor-arg> </bean> <context:annotation-config /> <tx:annotation-driven transaction-manager="springTransactionManager"/> <context:component-scan base-package="com.roden.jta" /> </beans>
3、java类
package com.roden.jta.controller;
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.roden.jta.service.TestService; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") @Controller public class TestController { @Autowired private TestService testService; //MySQL的数据库引擎必须是InnoDB,否则无法回滚 @Test public void test(){ testService.test(); } @Test public void test2(){ testService.update(); } @Test public void test3(){ testService.test3(); } } package com.roden.jta.service; public interface TestService { public String test(); public String update(); public void test3(); } package com.roden.jta.service.impl; import javax.annotation.Resource; import javax.transaction.SystemException; import javax.transaction.UserTransaction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.jta.JtaTransactionManager; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; import com.roden.jta.dao.TestMasterDao; import com.roden.jta.dao.TestSlaveDao; import com.roden.jta.service.TestService; @Service public class TestServiceImpl implements TestService{ @Resource(name = "springTransactionManager") private JtaTransactionManager txManager; @Autowired private TestMasterDao testMasterDao; @Autowired private TestSlaveDao testSlaveDao; @Resource(name = "transactionTemplate") private TransactionTemplate transactionTemplate; //编程式 @Override public String test() { UserTransaction userTx = txManager.getUserTransaction(); try { userTx.begin(); testMasterDao.master(); testSlaveDao.slave(); int a=1/0; System.out.println(a); userTx.commit(); } catch (Exception e) { System.out.println("捕获到异常,进行回滚" + e.getMessage()); e.printStackTrace(); try { userTx.rollback(); } catch (IllegalStateException e1) { System.out.println("IllegalStateException:" + e1.getMessage()); } catch (SecurityException e1) { System.out.println("SecurityException:" + e1.getMessage()); } catch (SystemException e1) { System.out.println("SystemException:" + e1.getMessage()); } } return null; } //声明式 @Override @Transactional public String update(){ testMasterDao.master(); testSlaveDao.slave(); //int a=1/0; //System.out.println(a); return null; } //事务模板方式 @Override public void test3() { transactionTemplate.execute(new TransactionCallbackWithoutResult(){ @Override protected void doInTransactionWithoutResult(TransactionStatus status) { try { testMasterDao.master(); testSlaveDao.slave(); int a=1/0; System.out.println(a); } catch (Exception ex) { // 通过调用 TransactionStatus 对象的 setRollbackOnly() 方法来回滚事务。 status.setRollbackOnly(); ex.printStackTrace(); } } }); /* //有返回值的回调 Object obj=transactionTemplate.execute(new TransactionCallback(){ @Override public Object doInTransaction(TransactionStatus status) { return 1; } }); */ } } package com.roden.jta.dao; public interface TestMasterDao { public String master(); public String update(); } package com.roden.jta.dao; public interface TestSlaveDao { public String slave(); } package com.roden.jta.dao.impl; import javax.annotation.Resource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import com.roden.jta.dao.TestMasterDao; @Repository public class TestMasterDaoImpl implements TestMasterDao{ @Resource(name="masterJdbcTemplate") JdbcTemplate masterJdbcTemplate; @Override public String master() { masterJdbcTemplate.execute("update teacher set name='master' where id=1"); return "success"; } @Override public String update() { masterJdbcTemplate.execute("update teacher set name='8' where id=1"); System.out.println("update"); masterJdbcTemplate.execute("fff teacher set name=''6' where id=1"); return null; } } package com.roden.jta.dao.impl; import javax.annotation.Resource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; impo d775 rt com.roden.jta.dao.TestSlaveDao; @Repository public class TestSlaveDaoImpl implements TestSlaveDao{ @Resource(name="slaveJdbcTemplate") JdbcTemplate slaveJdbcTemplate; @Override public String slave() { slaveJdbcTemplate.execute("update student set name='slave' where id=1"); return "success"; } }
数据源详细参数配置
<!-- 两个数据源的功用配置,方便下面直接引用 --> <bean id="abstractXADataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" abstract="true"> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/> <property name="poolSize" value="10" /> <property name="minPoolSize" value="10"/> <property name="maxPoolSize" value="30"/> <property name="borrowConnectionTimeout" value="60"/> <!--获取连接失败重新获等待最大时间,在这个时间内如果有可用连接,将返回--> <property name="reapTimeout" value="20"/> <!--最大获取数据时间,如果不设置这个值,Atomikos使用默认的5分钟,那么在处理大批量数据读取的时候,一旦超过5分钟,就会抛出类似 Resultset is close 的错误.--> <property name="maxIdleTime" value="60"/> <!--最大闲置时间,超过最小连接池连接的连接将将关闭--> <property name="maintenanceInterval" value="60" /> <!--连接回收时间--> <property name="loginTimeout" value="60" /> <!--java数据库连接池,最大可等待获取datasouce的时间--> <property name="logWriter" value="60"/> <property name="testQuery"> <value>select 1</value> </property> </bean> <!-- 配置第一个数据源 --> <bean id="dataSource" parent="abstractXADataSource"> <!-- value只要两个数据源不同就行,随便取名 --> <property name="uniqueResourceName" value="mysql/sitestone" /> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /> <property name="xaProperties"> <props> <prop key="URL">${jdbc.url}</prop> <prop key="user">${jdbc.username}</prop> <prop key="password">${jdbc.password}</prop> </props> </property> </bean> <!-- 配置第二个数据源--> <bean id="dataSourceB" parent="abstractXADataSource"> <!-- value只要两个数据源不同就行,随便取名 --> <property name="uniqueResourceName" value="mysql/sitesttwo" /> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /> <property name="xaProperties"> <props> <prop key="URL">${jdbca.url}</prop> <prop key="user">${jdbca.username}</prop> <prop key="password">${jdbca.password}</prop> </props> </property> </bean>
相关文章推荐
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- 分布式版本管理git入门指南使用资料汇总及文章推荐
- SQL Server误区30日谈 第1天 正在运行的事务在服务器故障转移后继续执行
- 浅析SQL Server中包含事务的存储过程
- Mysql中的事务是什么如何使用
- MySql的事务使用与示例详解
- C#分布式事务的超时处理实例分析
- C#中的事务用法实例分析
- Erlang分布式节点中的注册进程使用实例
- SQL Server的事务操作隔离模式介绍
- MySQL中事务概念的简洁学习教程
- C#处理Access中事务的方法
- oracle 合并查询 事务 sql函数小知识学习
- 模拟Spring的简单实现
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解
- sql不常用函数总结以及事务,增加,删除触发器