Spring分布式事务实现分布式事务是指操作多个数据库之间的事务,spring的org.springframework.transaction.jta.JtaTransactionManager,提供了分布式事务支持。
如果使用WAS的JTA支持,把它的属性改为WebSphere对应的TransactionManager。
在tomcat下,是没有分布式事务的,不过可以借助于第三方软件jotm(Java Open Transaction Manager )和AtomikosTransactionsEssentials实现,在spring中分布式事务是通过jta(jotm,atomikos)来进行实现。
1、/2、/Main/TransactionsEssentials一、使用JOTM例子(1) Dao及实现GenericDao接口:?1 2 3 4 public interface GenericDao {public int save(String ds, String sql, Object[] obj) throws Exception; public intfindRowCount(String ds, String sql);}GenericDaoImpl实现:?1 2 3 4 5 6 7 8 910111213141516171819202122232425262728 public class GenericDaoImpl implements GenericDao{private JdbcTemplatejdbcTemplateA;private JdbcTemplatejdbcTemplateB;public void setJdbcTemplateA(JdbcTemplatejdbcTemplate) {this.jdbcTemplateA = jdbcTemplate;}public void setJdbcTemplateB(JdbcTemplatejdbcTemplate) {this.jdbcTemplateB = jdbcTemplate;}public int save(String ds, String sql, Object[] obj) throws Exception{ if(null == ds || "".equals(ds)) return -1;try{if(ds.equals("A")){return this.jdbcTemplateA.update(sql, obj);}else{return this.jdbcTemplateB.update(sql, obj);}}catch(Exception e){e.printStackTrace();throw new Exception("执行" + ds + "数据库时失败!");}}public intfindRowCount(String ds, String sql) {293031323334353637 if(null == ds || "".equals(ds)) return -1;if(ds.equals("A")){return this.jdbcTemplateA.queryForInt(sql); }else{return this.jdbcTemplateB.queryForInt(sql); }}}(2) Service及实现UserService接口:?1 2 3 public interface UserService {public void saveUser() throws Exception; }UserServiceImpl实现:?1 2 3 4 5 6 7 8 9101112131415161718192021222324 public class UserServiceImpl implements UserService{private GenericDaogenericDao;public void setGenericDao(GenericDaogenericDao) {this.genericDao = genericDao;}public void saveUser() throws Exception {String userName = "user_" + Math.round(Math.random()*10000); System.out.println(userName);StringBuildersql = new StringBuilder();sql.append(" insert into t_user(username, gender) values(?,?); "); Object[] objs = new Object[]{userName,"1"};genericDao.save("A", sql.toString(), objs);sql.delete(0, sql.length());sql.append(" insert into t_user(name, sex) values(?,?); ");objs = new Object[]{userName,"男的"};//值超出范围genericDao.save("B", sql.toString(), objs);}}(3) applicationContext-jotm.xml ?1 2 3 <?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans" xmlns:xsi="/2001/XMLSchema-instance"4 5 6 7 8 910111213141516171819202122232425262728293031323334353637383940414243444546474849505152 xmlns:context="/schema/context"xmlns:aop="/schema/aop"xmlns:tx="/schema/tx"xsi:schemaLocation="/schema/beans /schema/beans/s /schema/context /schema/context/spring-context-2.5.x /schema/tx /schema/tx/spring-tx-2.5.xsd/schema/aop /schema/aop/spring-aop-2.5.xsd"><description>springJTA</description><!--指定Spring配置中用到的属性文件--><bean id="propertyConfig"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="locations"><list><value>classpath:jdbc.properties</value></list></property></bean><!-- JOTM实例--><bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"><property name="defaultTimeout" value="500000"/></bean><!-- JTA事务管理器--><bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"><property name="userTransaction" ref="jotm" /></bean><!-- 数据源A --><bean id="dataSourceA" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"><property name="dataSource"><bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"><property name="transactionManager" ref="jotm"/><property name="driverName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/></bean></property><property name="user" value="${ername}"/><property name="password" value="${jdbc.password}"/></bean><!-- 数据源B --><bean id="dataSourceB" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"><property name="dataSource"><bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"><property name="transactionManager" ref="jotm"/><property name="driverName" value="${jdbc2.driver}"/>535455565758596061626364656667686970717273747576777879808182838485868788899091 <property name="url" value="${jdbc2.url}"/></bean></property><property name="user" value="${ername}"/><property name="password" value="${jdbc2.password}"/></bean><bean id = "jdbcTemplateA"class = "org.springframework.jdbc.core.JdbcTemplate"><property name = "dataSource" ref="dataSourceA"/></bean><bean id = "jdbcTemplateB"class = "org.springframework.jdbc.core.JdbcTemplate"><property name = "dataSource" ref="dataSourceB"/></bean><!-- 事务切面配置--><aop:config><aop:pointcut id="pointCut"expression="execution(* com.logcd.service..*.*(..))"/><!-- 包及其子包下的所有方法--><aop:advisorpointcut-ref="pointCut" advice-ref="txAdvice"/><aop:advisorpointcut="execution(* *mon.service..*.*(..))" advice-ref="txAdvice"/></aop:config><!-- 通知配置--><tx:advice id="txAdvice" transaction-manager="jtaTransactionManager"><tx:attributes><tx:method name="delete*" rollback-for="Exception"/><tx:method name="save*" rollback-for="Exception"/><tx:method name="update*" rollback-for="Exception"/><tx:method name="find*" read-only="true" rollback-for="Exception"/></tx:attributes></tx:advice><bean id="genericDao" class="com.logcd.dao.impl.GenericDaoImpl" autowire="byName"></bean><bean id="userService" class="erServiceImpl" autowire="byName"></bean> </beans>(4) 测试?1 2 3 4 5 6 7 public class TestUserService{private static UserServiceuserService;@BeforeClasspublic static void init(){ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext-jotm.xml");8 9101112131415161718192021 userService = (UserService)app.getBean("userService"); }@Testpublic void save(){System.out.println("begin...");try{userService.saveUser();}catch(Exception e){System.out.println(e.getMessage());}System.out.println("finish...");}}二、关于使用atomikos实现(1) 数据源配置?1 2 3 4 5 6 7 8 91011121314151617181920212223 <bean id="dataSourceA" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close"> <property name="uniqueResourceName"><value>${datasource.uniqueResourceName}</value></property><property name="xaDataSourceClassName"><value>${database.driver_class}</value></property><property name="xaDataSourceProperties"><value>URL=${database.url};user=${ername};password=${database.password}</value></property><property name="exclusiveConnectionMode"><value>${connection.exclusive.mode}</value></property><property name="connectionPoolSize"><value>${connection.pool.size}</value></property><property name="connectionTimeout"><value>${connection.timeout}</value></property><property name="validatingQuery"><value>SELECT 1</value></property></bean>(2)、事务配置?1 2 <bean id="atomikosTransactionManager" class="erTransactionManager" init-method="init" destroy-method="close">3 4 5 6 7 8 9101112131415161718192021222324252627 <property name="forceShutdown" value="true"/></bean><bean id="atomikosUserTransaction" class="erTransactionImp"><property name="transactionTimeout" value="${transaction.timeout}"/></bean><!-- JTA事务管理器--><bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager" ref="atomikosTransactionManager"/><property name="userTransaction" ref="atomikosUserTransaction"/></bean><!-- 事务切面配置--><aop:config><aop:pointcut id="serviceOperation" expression="execution(* *..service*..*(..))"/><aop:advisorpointcut-ref="serviceOperation" advice-ref="txAdvice"/></aop:config><!-- 通知配置--><tx:advice id="txAdvice" transaction-manager="springTransactionManager"><tx:attributes><tx:method name="*" rollback-for="Exception"/></tx:attributes></tx:advice>有关JTAJTA全称为Java Transaction API,顾名思义JTA定义了一组统一的事务编程的接口,这些接口如下:XAResourceXAResource接口是对实现了X/Open CAE规范的资源管理器(Resource Manager,数据库就是典型的资源管理器) 的抽象,它由资源适配器(Resource Apdater) 提供实现。