博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring+Mybatis多数据源的一种实现方式,支持事务
阅读量:6290 次
发布时间:2019-06-22

本文共 6589 字,大约阅读时间需要 21 分钟。

最近一个项目用到了多个数据库,所以需要实现动态切换数据源来查询数据,http://www.cnblogs.com/lzrabbit/p/3750803.html这篇文章让我受益匪浅,提供了一种自动切换数据源的思路,但这种方式不支持事务,所以我进一步改进了这个方案,下面直入正题

多数据源配置:

#============================================================================# DataBaseOne#============================================================================jdbc.one.driver=com.mysql.jdbc.Driverjdbc.one.url=jdbc:mysql://127.0.0.1:3306/DataBaseOne?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=truejdbc.one.username=rootjdbc.one.password=root=============================================================================#============================================================================# DataBaseTwo#============================================================================jdbc.two.driver=com.mysql.jdbc.Driverjdbc.two.url=jdbc:mysql://127.0.0.1:3306/DataBaseTwo?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=truejdbc.two.username=rootjdbc.two.password=root=============================================================================#============================================================================# DataBaseThree#============================================================================jdbc.three.driver=com.mysql.jdbc.Driverjdbc.three.url=jdbc:mysql://127.0.0.1:3306/DataBaseThree?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=truejdbc.three.username=rootjdbc.mysql.password=root=============================================================================#============================================================================# 通用配置#============================================================================jdbc.initialSize=5jdbc.minIdle=5jdbc.maxIdle=20jdbc.maxActive=100jdbc.maxWait=100000jdbc.defaultAutoCommit=falsejdbc.removeAbandoned=truejdbc.removeAbandonedTimeout=600jdbc.testWhileIdle=truejdbc.timeBetweenEvictionRunsMillis=60000jdbc.numTestsPerEvictionRun=20jdbc.minEvictableIdleTimeMillis=300000

Spring中使用多数据源:

MultipleDataSource.java实现:

package com.cnblogs.datasource;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/** 多数据源java实现 */public class MultipleDataSource extends AbstractRoutingDataSource {    private static final ThreadLocal
dataSourceKey = new InheritableThreadLocal
(); public static void setDataSourceKey(String dataSource) { dataSourceKey.set(dataSource); } @Override protected Object determineCurrentLookupKey() { return dataSourceKey.get(); }}

下面详解使用SpringAOP来实现数据源切换,并支持事务控制

上面我们配置的AOP是针对service层的,所以在调用service层的任何方法时都会经过AOP,因此我们就在AOP中先于service调用时把数据源切换,看代码

新建类MultipleDataSourceAspectAdvice,把MultipleDataSourceAspectAdvice.java放在spring能自动注入的包中,比如controller包,或者自己把这个类所在的包加入到component-scan配置中去,总之要要让spring能自动加载

package com.cnblogs.controller;import org.apache.log4j.Logger;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;import com.cnblogs.datasource.MultipleDataSource;import com.cnblogs.service.DataBaseOne;import com.cnblogs.service.DataBaseTwo;import com.cnblogs.service.DataBaseThree;/** * 数据库链接自动切换AOP处理 * Order优先级设置到最高,因为在所有service方法调用前都必须把数据源确定 * Order数值越小优先级越高 */@Component@Aspect@Order(1)public class MultipleDataSourceAspectAdvice {    private static final Logger LOGGER = Logger.getLogger(MultipleDataSourceAspectAdvice.class);    public MultipleDataSourceAspectAdvice() {        LOGGER.info("MultipleDataSourceAspectAdvice 加载成功");    }    /**     * 定义切面     */    @Pointcut("execution(* com.cnblogs.service.*.*(..))")    public void pointCut() {    }    // dataSourceOneKey    // dataSourceTwoKey    // dataSourceThreeKey    @Around("pointCut()")    public Object doAround(ProceedingJoinPoint jp) throws Throwable {        if (jp.getTarget() instanceof DataBaseOne) {            LOGGER.debug("使用数据库链接:dataSourceOneKey");            MultipleDataSource.setDataSourceKey("dataSourceOneKey");        } else if (jp.getTarget() instanceof DataBaseTwo) {            LOGGER.debug("使用数据库链接:dataSourceTwoKey");            MultipleDataSource.setDataSourceKey("dataSourceTwoKey");        } else if (jp.getTarget() instanceof DataBaseThree) {            LOGGER.debug("使用数据库链接:dataSourceThreeKey");            MultipleDataSource.setDataSourceKey("dataSourceThreeKey");        } else {            // 默认是dataSourceOneKey            LOGGER.debug("使用数据库链接:dataSourceOneKey");            MultipleDataSource.setDataSourceKey("dataSourceOneKey");        }        return jp.proceed();    }}

到这里我们所以的spring多数据源配置已经完毕,那如何在执行service方法时让service切换到正确的数据库呢?上面的类中定义了有3个类DataBaseOne,DataBaseTwo,DataBaseThree,这3个类其实只是一个interface,没有任何实现方法,我们让具体业务的service都继承至这3个类以区分不同的service对应不同的数据源,因为业务的service我是知道他用的哪个数据源的,比如FooService继承至DataBaseOne,则在使用FooService任何方法时AOP就会先把数据源切换到dataSourceOneKey,以此就达到了自动切换数据源的目的,并且支持事务,下面看代码:

package com.cnblogs.service;/** * DataBaseOne数据库占位类 * 详情参见 MultipleDataSourceAspectAdvice 类 */public interface DataBaseOne {}

DataBaseTwo,DataBaseThree与这完全相同

至此多数据源就配置完毕,可以安心写业务逻辑了

原理部分博友http://www.cnblogs.com/lzrabbit/p/3750803.html讲的十分清楚,再次感谢

转载于:https://www.cnblogs.com/ieinstein/p/9049749.html

你可能感兴趣的文章
编译器的工作过程
查看>>
Oracle 12C 新特性之表分区或子分区的在线迁移
查看>>
Centos 安装ixgbe驱动
查看>>
【BZOJ2589】 Spoj 10707 Count on a tree II
查看>>
select2使用时遇到的一些坑(4.x.x以上版本)
查看>>
(转).net中的session与cookies区别及使用方法
查看>>
Linux基于php-fpm模式的lamp搭建phpmyadmin的方法
查看>>
rsync同步工具的配置与使用
查看>>
浅谈现公司的Spring Cloud微服务框架
查看>>
【OCP-12c】CUUG 071题库考试原题及答案解析(17)
查看>>
RAC RMAN 备份 RMAN-03009 ORA-19504 ORA-27040 RMAN-06012 channel c3 not allocated 错误分析
查看>>
[转]指针函数与函数指针的区别
查看>>
【转】Terracotta's Scalability Story
查看>>
Python 词频统计
查看>>
种类并查集,TOJ(1706)
查看>>
java PO、BO
查看>>
docker拉取镜像报错:net/http: TLS handshake timeout.
查看>>
sublime text笔记
查看>>
为CommonMark.Net增加Table解析
查看>>
multi_index_container 多索引容器
查看>>