双数据源配置

从此抄录:https://blog.csdn.net/ll535299/article/details/78203634

1、先配置两个数据源,附上主要代码,给自己回忆,详解见开头链接

<!-- 配置数据源 -->
<bean id="szDS" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <property name="url" value="${szds.dbhost}"/>
    <property name="username" value="${szds.dbusername}"/>
    <property name="password" value="${szds.dbpwd}"/>
    <property name="initialSize" value="1"/>
    <property name="minIdle" value="1"/>
    <property name="maxActive" value="30"/>
    <property name="maxWait" value="${szds.maxWait}"/>
    <property name="timeBetweenEvictionRunsMillis" value="${szds.timeBetweenEvictionRunsMillis}"/>
    <property name="minEvictableIdleTimeMillis" value="${szds.minEvictableIdleTimeMillis}"/>
    <property name="validationQuery" value="SELECT 'j'"/>
    <property name="testWhileIdle" value="true"/>
    <property name="testOnBorrow" value="false"/>
    <property name="testOnReturn" value="false"/>
    <property name="poolPreparedStatements" value="false"/>
    <property name="filters" value="${szds_common.filters}"/>
    <property name="connectionProperties" value="${szds_common.connectionProperties}"/>
</bean>
<!-- 配置上报系统数据源 -->
<bean id="tntDS" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <property name="url" value="${szds_tnt.dbhost}"/>
    <property name="username" value="${szds_tnt.dbusername}"/>
    <property name="password" value="${szds_tnt.dbpwd}"/>
    <property name="initialSize" value="1"/>
    <property name="minIdle" value="1"/>
    <property name="maxActive" value="30"/>
    <property name="maxWait" value="${szds_tnt.maxWait}"/>
    <property name="timeBetweenEvictionRunsMillis" value="${szds_tnt.timeBetweenEvictionRunsMillis}"/>
    <property name="minEvictableIdleTimeMillis" value="${szds_tnt.minEvictableIdleTimeMillis}"/>
    <property name="validationQuery" value="SELECT 'j'"/>
    <property name="testWhileIdle" value="true"/>
    <property name="testOnBorrow" value="false"/>
    <property name="testOnReturn" value="false"/>
    <property name="poolPreparedStatements" value="false"/>
    <property name="filters" value="${szds_common.filters}"/>
    <property name="connectionProperties" value="${szds_common.connectionProperties}"/>
</bean>

2、自定义一个数据源类,该类继承 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource并重写determineCurrentLookupKey()方法

public class RoutingDataSource extends AbstractRoutingDataSource  {

     @Override
     protected Object determineCurrentLookupKey() {
            return DataSourceHolder.getDataSourceType();
     }

}

3、将该类交由sping管理,其在spring配置文件中配置如下

<bean id="dataSource" class="com.wayyue.sz.asgard.admin.dataSource.RoutingDataSource">
    <!-- 为targetDataSources注入两个数据源 -->
    <property name="targetDataSources">
        <map key-type="java.lang.String">
            <entry key="szDS" value-ref="szDS"/>
            <entry key="tntDS" value-ref="tntDS"/>
        </map>
    </property>
    <!-- 为指定数据源RoutingDataSource注入默认的数据源-->
    <property name="defaultTargetDataSource" ref="szDS"/>
</bean>

4、事务配置如下

<!-- 开启aop注解-->
<aop:aspectj-autoproxy proxy-target-class="true"/>

<!-- mybatis 配置-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mapperLocations" value="classpath:sqlmap/*.xml"/>
</bean>

<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.wayue.sz.biz.orm.mapper"/>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

<!--  配置事物管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<!--  开启注解控制事物-->
<tx:annotation-driven transaction-manager="transactionManager"/>

5、编写一个数据源持有类DataSourceHolder

package com.wayyue.sz.asgard.admin.dataSource;

public class DataSourceHolder {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    /**
     * 设置数据源类型
     *
     * @param dataSourceType 数据库类型
     */
    public static void setDataSourceType(String dataSourceType) {
        contextHolder.set(dataSourceType);
    }

    /**
     * 获取数据源类型
     *
     * @return
     */
    public static String getDataSourceType() {
        return contextHolder.get();
    }

    /**
     * 清除数据源类型
     */
    public static void clearDataSourceType() {
        contextHolder.remove();
    }

}

6.自定义注解

package com.wayyue.sz.asgard.admin.aspect;

import java.lang.annotation.*;

/**
 * 数据源
 *
 * @author xxx
 * @date 2018年11月19日21:05:13
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource {

    String value() default "";

}

7、动态切换数据源

package com.wayyue.sz.asgard.admin.aspect;

import com.wayyue.sz.asgard.admin.dataSource.DataSourceHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Repository;

import java.lang.reflect.Method;

@Aspect
@Repository
public class DataSourceAspect {

    @Pointcut("execution(* com.wayyue.sz.asgard.admin.service.tnt..*.*(..))")
    private void anyMethod() {
    }

    @AfterReturning(value = "anyMethod()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        DataSourceHolder.clearDataSourceType();
    }

    @Before(value = "anyMethod()")
    public void before(JoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        //如果方法体上使用了DataSource注解
        if (method.isAnnotationPresent(DataSource.class)) {
            //获取该方法上的注解名
            DataSource datasource = method.getAnnotation(DataSource.class);

            //将方法体上的注解的值赋予给DataSourceHolder数据源持有类
            DataSourceHolder.setDataSourceType(datasource.value());
        }
    }

}

8、若方法体上没有注解,则都是使用默认数据源,如果有以下注解,则使用指定的数据源

@Override
@DataSource("tntDS")
public String getDeal() { // 新数据源

    String s = tntDealInfoMapper.dockingOrderCode();
    return s;
}

@Override
public String getCode() { // 默认数据源

    return tntDealInfoMapper.getCode();
}
原文地址:https://www.cnblogs.com/liuye007/p/9987237.html