首页 > 其他 > 详细

多数据源切换配合事务问题

时间:2019-10-21 17:33:57      阅读:57      评论:0      收藏:0      [点我收藏+]

用DynamicDataSource类辅助切换多数据源

实现AbstractRoutingDataSource接口,在类中定义

public static final String plateBaseDataSource= "plateBaseDataSource";
public static final String lgCommonDataSource= "lgCommonDataSource";
public static final String subApplicationDataSource= "subApplicationDataSource";
public static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(){};

切换与清空数据缘方法为

    public static void clearCustomerDataSource(){
        contextHolder.remove();
    }
    
    public static void setCustomerDataSource(String customerType){
        contextHolder.set(customerType);
    }

 

对应配置文件中,数据源定义为

    <bean id="plateBaseDataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${plateBase.driverClassName}" />
        <property name="url" value="${plateBase.url}" />
        <property name="username" value="${plateBase.uname}" />
        <property name="password" value="${plateBase.password}" />
        <!-- 连接池启动时的初始值 -->
        <property name="initialSize" value="${plateBase.initialSize}" />
        <!-- 连接池的最大值 -->
        <property name="maxActive" value="${plateBase.maxActive}" />
        <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
        <property name="maxIdle" value="${plateBase.maxIdle}" />
        <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
        <property name="minIdle" value="${plateBase.minIdle}" />
        <property name="validationQuery" value="select 1 from dual"></property>
    </bean>
    
    <bean id="lgCommonDataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${lgCommon.driverClassName}" />
        <property name="url" value="${lgCommon.url}" />
        <property name="username" value="${lgCommon.uname}" />
        <property name="password" value="${lgCommon.password}" />
        <!-- 连接池启动时的初始值 -->
        <property name="initialSize" value="${lgCommon.initialSize}" />
        <!-- 连接池的最大值 -->
        <property name="maxActive" value="${lgCommon.maxActive}" />
        <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
        <property name="maxIdle" value="${lgCommon.maxIdle}" />
        <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
        <property name="minIdle" value="${lgCommon.minIdle}" />
        <property name="validationQuery" value="select 1 from dual"></property>
    </bean>

定义DataSource为

    <bean id="dataSource" class="heb.ysbs.utils.lgcommon.DynamicDataSource">
        <property name="defaultTargetDataSource" ref="${defaultTargetDataSource}"/>
         <property name="customDefaultDataSource" value="${defaultTargetDataSource}"/>
         <property name="customLgBaseLogTableName" value="${customLgBaseLogTableName}"/>
        <property name="targetDataSources" >
            <map>
                <entry key="plateBaseDataSource" value-ref="plateBaseDataSource"/>
                <entry key="lgCommonDataSource" value-ref="lgCommonDataSource"/>
            </map>
        </property>
    </bean>

jdbctemplate常规定义,没什么好讲

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource" />
    </bean>

以上为数据源切换部分 ,这时切换数据源可直接调用DynamicDataSource.clearCustomerDataSource,在配置事务后,进入事务线程后jdbc得到默认DataSource,DynamicDataSource方法设置数据源在事务中执行的jdbc中不体现(线程问题,一知半解)

解决方法是在事务开启前切换数据源,用aop增强

定义工具类

<bean id="dataSourceExchange" class="fasp.utils.lgcommon.DataSourceExchange"></bean>

定义切片,排序在事务之前 :事务切点order=2,

    <aop:config proxy-target-class="true">
        <aop:pointcut id="dataSourcetransactionPointcut" expression="(execution(* fasp.service.lgcommon..*.*(..))) )" />
        <aop:aspect id="aspect" ref="dataSourceExchange" order="1" >
            <aop:before method="before" pointcut-ref="dataSourcetransactionPointcut" /> 
             <aop:after method="after" pointcut-ref="dataSourcetransactionPointcut" /> 
        </aop:aspect>
    </aop:config> 

个人习惯,感觉定义两个切点灵活,这里没有必要每个方法都进行数据切换如果也用 在一个aop:pointcut 定义两个aop:advisor就还要在拦截器中判断调用方法,其他资料中看到的

invoke方法

package com.lei.demo.aop.schema;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class HelloAroundAdvice implements MethodInterceptor {

    public Object invoke(MethodInvocation arg0) throws Throwable {

        System.out.println("++++++before advice");
        arg0.proceed();
        System.out.println("++++++after advice");
        
        return null;
    }

}

工具类DataSourceExchange中方法

技术分享图片
 1 /**
 2      * 事务加载前执行
 3      * 切换数据源
 4      * @param call
 5      */
 6     public void before(JoinPoint call){
 7 
 8         Object[] obj=call.getArgs();//参数集合
 9         String dataSourceName=(String)(obj[0]);//规则:默认第一个参数为datasourcename
10         //Signature signature=call.getSignature(); //参数类型集合
11         //    String [] argNames= ( (MethodSignature) signature ).getParameterNames();//参数名
12         DynamicDataSource.setCustomerDataSource( dataSourceName);
13 
14     }
15     /**
16      * 事务加载前执行
17      * 清空数据源
18      * @param call
19      */
20     public void after(JoinPoint call){
21         DynamicDataSource.clearCustomerDataSource();
22         //String parameter= DynamicDataSource.getCustomDefaultDataSource();
23         //DynamicDataSource.setCustomerDataSource(parameter);
24     }
25 }
View Code

 

多数据源切换配合事务问题

原文:https://www.cnblogs.com/Isolate/p/11714723.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!