多数据源配置 情况 下的事务管理

来源:互联网 发布:手机淘宝延长收货 编辑:程序博客网 时间:2024/06/06 20:50
可以是分布式事务管理也可以是简单的datasourceTranctionManager.但是我们建议不做分布式事务管理,尽量保证一个事务下只操作一个数据库, 保持服务的功能单一性,如果一个服务会操作到两个数据库中的数据,那涉及到的所有表最好放到同一个数据库中。 因为分布式事务管理,消耗资源严重,性能下降。如果不是分布式事务管理,又有多个数据源,我们就要配置多个事务管理器了,哈哈,每个数据源配置一个。这样我们 再服务上配置使用的事务的时候,就要配置指定的事务管理器了。此外如果我们用到了 mybatis 或者hibernate 框架的话,sessionfactory  也是需要配置多个的。现在我们有两个服务a和b,分别操作一个数据库,如果a 中 又调用b服务,这时候实际上 a服务  是操作了多个数据源的,如果要保证事务一致性,就需要 判断 b服务的返回结果,如果b服务中,出错了会抛异常,那我们就try catch b 服务,并且  重新在a 中 把这个异常抛出。如果b服务中,始终返回结果,并且结果的状态是错误的,我们就不能 trycatch了,而是判断返回结果的状态,如果是错误的就在a 中抛出异常。如果是分布式事务管理,意味着项目里有服务 需要操作多个数据库,并且要做到事务一致性。spring的org.springframework.transaction.jta.JtaTransactionManager,提供了分布式事务支持。如果使用WAS的JTA支持,把它的属性改为WebSphere对应的TransactionManager。     在tomcat下,是没有分布式事务的,不过可以借助于第三方软件jotm(Java Open Transaction Manager )和AtomikosTransactionsEssentials实现,在spring中分布式事务是通过jta(jotm,atomikos)来进行实现。 1、http://jotm.objectweb.org/ 2、http://www.atomikos.com/Main/TransactionsEssentials 一、使用JOTM例子 (1)、Dao及实现 public interface GenericDao {        public int save(String ds, String sql, Object[] obj) throws Exception;            public int findRowCount(String ds, String sql);        }  public class GenericDaoImpl implements GenericDao{        private  JdbcTemplate jdbcTemplateA;      private  JdbcTemplate jdbcTemplateB;        public void setJdbcTemplateA(JdbcTemplate jdbcTemplate) {          this.jdbcTemplateA = jdbcTemplate;      }        public void setJdbcTemplateB(JdbcTemplate jdbcTemplate) {          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 int findRowCount(String ds, String sql) {          if(null == ds || "".equals(ds)) return -1;                    if(ds.equals("A")){              return this.jdbcTemplateA.queryForInt(sql);          }else{              return this.jdbcTemplateB.queryForInt(sql);          }      }    }  (2)、Service及实现 public interface UserService {            public void saveUser() throws Exception;        }  public class UserServiceImpl implements UserService{        private GenericDao genericDao;            public void setGenericDao(GenericDao genericDao) {          this.genericDao = genericDao;      }        public void saveUser() throws Exception {          String userName = "user_" + Math.round(Math.random()*10000);          System.out.println(userName);                    StringBuilder sql = 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 <?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:context="http://www.springframework.org/schema/context"       xmlns:aop="http://www.springframework.org/schema/aop"       xmlns:tx="http://www.springframework.org/schema/tx"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd       http://www.springframework.org/schema/aop http://www.springframework.org/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="${jdbc.username}"/>          <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}"/>                  <property name="url" value="${jdbc2.url}"/>              </bean>          </property>          <property name="user" value="${jdbc2.username}"/>          <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:advisor pointcut-ref="pointCut" advice-ref="txAdvice"/>                     <aop:advisor pointcut="execution(* *..common.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="com.logcd.service.impl.UserServiceImpl" autowire="byName">      </bean>    </beans>  (4)、测试 public class TestUserService{        private static UserService userService;            @BeforeClass      public static void init(){          ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext-jotm.xml");          userService = (UserService)app.getBean("userService");      }            @Test      public void save(){          System.out.println("begin...");          try{              userService.saveUser();          }catch(Exception e){              System.out.println(e.getMessage());          }          System.out.println("finish...");      }        }  二、关于使用atomikos实现 (1)、数据源配置 <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=${database.username};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)、事务配置 <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"       init-method="init" destroy-method="close">       <property name="forceShutdown" value="true"/>   </bean>     <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">       <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:advisor pointcut-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>
原创粉丝点击