spring编程式事务支持多数据源事务控制

文章参考:https://www.cnblogs.com/shuaiandjun/p/8667815.html

项目框架是jdbcTemplat+spring+struts2,项目需求是需要在一个方法中实现多个数据库的访问,并实现多数据源的事务控制。可直接复制使用。

下面直接贴代码和解决方案

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
   
   <bean id="datasource2016" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@*:1521/orcl" />
        <property name="username" value="****" />
        <property name="password" value="***" />
   </bean>
   
   <bean id="datasource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@*:1521/orcl" />
        <property name="username" value="***" />
        <property name="password" value="***" />
   </bean>

   <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  
        <property name="dataSource" ref="datasource2016" />  
    </bean> 
    
   <bean id="jdbcTemplate1" class="org.springframework.jdbc.core.JdbcTemplate">  
        <property name="dataSource" ref="datasource1" />  
    </bean>
    
    <bean id="bgdDataSource1" class="com.bgd.platform.util.dao.BgdDataSource">
        <property name="jdbcTemplate" ref="jdbcTemplate" />  
        <property name="transactionTemplate" ref="transactionTemplate" />
        <property name="abstractBgdDBSql" ref="abstractBgdDBSql" />
    </bean>
    
   <bean id="bgdDataSourcefk" class="com.bgd.platform.util.dao.BgdDataSource">  
        <property name="jdbcTemplate" ref="jdbcTemplate1" />  
        <property name="transactionTemplate" ref="transactionTemplate1" />
        <property name="abstractBgdDBSql" ref="abstractBgdDBSql" />
    </bean>

   <bean id="bgdDataSource" class="com.bgd.platform.util.dao.BgdDataSourceMulti">
        <property name="defaultDataSource">
         <ref bean="bgdDataSource1" />
      </property>
      <property name="dataSources">
         <map>
            <entry key="ql">
               <ref bean="bgdDataSource1" />
            </entry>
            <entry key="fk">
               <ref bean="bgdDataSourcefk" />
            </entry>
         </map>
      </property> 
    </bean>
   
   <bean id="bgdDataSourceKylin" class="com.bgd.platform.util.dao.BgdDataSourceKylin">
          <property name="dataSourceKylin" ref="dataSourcekylin"/>
   </bean>


   <bean id="abstractBgdDBSql" class="com.bgd.platform.util.dao.BgdDBSqlOracle">  
    </bean> 
    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
        <property name="dataSource" ref="datasource2016"/> 
    </bean> 
    
   <bean id="transactionManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
        <property name="dataSource" ref="datasource1"/> 
    </bean>
    
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">  
        <property name="transactionManager" ref="transactionManager" />  
    </bean>
    
   <bean id="transactionTemplate1" class="org.springframework.transaction.support.TransactionTemplate">  
        <property name="transactionManager" ref="transactionManager1" />  
    </bean>

    <bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref="transactionManager"/>
        <property name="target" ref="bgdDataSource"/>
        <property name="transactionAttributes">
            <props>
                <!--
               transactionAttributes属性可以设置事务处理的方式,事务隔离级别,是否只读三个属性,用逗号隔开
               事务隔离级别各数据库系统不完全支持,一般不设置,用默认的即可
               事务处理选项有如下几个:(前面2个常用)
               PROPAGATION_REQUIRED      - 需要事务处理。如果当前不存在事务环境,则创建一个
               PROPAGATION_SUPPORTS      - 如果当前存在事务环境,则作为其中的一部分。如果不存在,则按非事务方式执行
               PROPAGATION_REQUIRES_NEW   - 需要事务处理。并总是开启一个新事务。如果已经存在事务环境,则挂起之
               PROPAGATION_MANDATORY     - 执行到指定方法时,必须已经存在事务环境,否则出错
               PROPAGATION_NEVER     - 不支持事务操作,如果存在事务环境会出错
               PROPAGATION_NOT_SUPPORTED  - 不支持事务操作。如果存在事务,则挂起
            -->
                <prop key="*">PROPAGATION_REQUIRED,-Exception</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionProxy1" class="com.bgd.platform.util.dao.TransactionManagerIntercetor">
       <property name="transactionManagerBeanNames">
            <list>
                <value>transactionManager</value>
                <value>transactionManager1</value>
            </list>
        </property>
        <property name="target" ref="bgdDataSource1"/>
    </bean>

    <bean id="transactionProxyMulti"  class="org.springframework.aop.framework.ProxyFactoryBean" >
        <property name="interceptorNames">
            <list>
                <value>transactionProxy1</value>
            </list>
        </property>
    </bean>
</beans>
<bean name="menuManageBo" class="com.bgd.platform.sys.user.service.MenuManageService">
    <property name="bgdDataSource" ref="bgdDataSource" />
</bean>

<bean id="menuManageService"  parent="transactionProxyMulti">
    <property name="target">
        <ref bean="menuManageBo" />
    </property>
</bean>

<bean name="menuManageAction" class="com.bgd.platform.sys.user.action.MenuManageAction">
   <property name="menuManageService" ref="menuManageService"/>
</bean>

代理多个数据源代码:

package com.bgd.platform.util.dao;

import com.bgd.platform.util.service.SpringContextUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import java.util.List;
import java.util.Stack;

public class TransactionManagerIntercetor implements MethodInterceptor {

    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    private List<String> transactionManagerBeanNames;

    public void setTransactionManagerBeanNames(List transactionManagerBeanNames) {
        this.transactionManagerBeanNames = transactionManagerBeanNames;
    }

    private boolean openTransaction(Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack,
                                    Stack<TransactionStatus> transactionStatuStack) {
        for (String beanName : transactionManagerBeanNames) {
            DataSourceTransactionManager dataSourceTransactionManager = (DataSourceTransactionManager) SpringContextUtil.getBean(beanName);
            TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
            transactionStatuStack.push(transactionStatus);
            dataSourceTransactionManagerStack.push(dataSourceTransactionManager);
        }
        return true;
    }

    private void commit(Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack, Stack<TransactionStatus> transactionStatuStack){
        while (!dataSourceTransactionManagerStack.isEmpty()) {
            dataSourceTransactionManagerStack.pop().commit(
                    transactionStatuStack.pop());
        }
    }

    private void rollback(Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack,
                          Stack<TransactionStatus> transactionStatuStack){
        while (!dataSourceTransactionManagerStack.isEmpty()) {
            dataSourceTransactionManagerStack.pop().rollback(
                    transactionStatuStack.pop());
        }
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack = new Stack<DataSourceTransactionManager>();
        Stack<TransactionStatus> transactionStatuStack = new Stack<TransactionStatus>();
        Object retVal = null;
        try {
            if (!openTransaction(dataSourceTransactionManagerStack, transactionStatuStack)) {
                return null;
            }
            retVal = invocation.proceed();
            commit(dataSourceTransactionManagerStack, transactionStatuStack);
        } catch(Exception e) {
            rollback(dataSourceTransactionManagerStack, transactionStatuStack);
            throw e;
        }
        return retVal;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值