在平常的项目开发中,会遇到一个应用中访问多个数据源的需求,本文将通过使用SpringAop+Mybatis与spring-jdbc的

AbstractRoutingDataSource实现动态切换数据源;

1.定义多个数据源的枚举:

public enum DataSourceType {//第一个数据源DATASOURCE_ONE,//第二个数据源USERCENTER_TWO
}

2.定义动态扫描的注解:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DynamicDataSourceAnnotation {//dataSource 自定义注解的参数DataSourceType dataSource() default DataSourceType.DATASOURCE_ONE;
}

3.定义全局数据源的管理类,默认访问DATASOURCE_ONE

public class DataSourceTypeManager {private static final ThreadLocal<DataSourceType> dataSourceTypes  = new ThreadLocal<DataSourceType>() {protected DataSourceType initialValue() {return DataSourceType.DATASOURCE_ONE;}};public static DataSourceType get(){return dataSourceTypes.get();}public static void set(DataSourceType dataSourceType){dataSourceTypes.set(dataSourceType);}public static void reset(){dataSourceTypes.set(DataSourceType.DATASOURCE_ONE);}
}

4.实现AbstractRoutingDataSource动态路由数据源:

public class DynamicDataSource extends AbstractRoutingDataSource {private static final Logger logger = LoggerFactory.getLogger(AbstractRoutingDataSource.class);@Overrideprotected Object determineCurrentLookupKey() {logger.info("dataSourceType = "+ DataSourceTypeManager.get());return DataSourceTypeManager.get();}
}

5.定义AOP的Aspect动态切换数据源:

@Aspect
@Component
@Order(0)
public class DynamicDataSourceAspect {@Pointcut("execution( * com.test.datasource.manage.dao.mapper.*.*(..))")public void invanyMethod() {};//前置通知,设置成目标数据源@Before("invanyMethod()")public void beforeinv(JoinPoint jp) throws Exception {//获得注解DynamicDataSourceAnnotation meta = giveAnnotation(jp);DataSourceTypeManager.set(meta.dataSource());}//执行结束后设置成住数据源/*** 获得方法上的注解* @param joinPoint 切入点* @return* @throws Exception*/private DynamicDataSourceAnnotation giveAnnotation(JoinPoint joinPoint) throws Exception {Signature signature = joinPoint.getSignature();MethodSignature methodSignature = (MethodSignature) signature;Method method = methodSignature.getMethod();if (method != null) {return method.getAnnotation(DynamicDataSourceAnnotation.class);}return null;}@After("invanyMethod()")public void after(JoinPoint jp) throws Exception {DataSourceTypeManager.set(DataSourceType.DATASOURCE_ONE);}

6.mybatis配置文件

<?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:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.3.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.3.xsd"><!-- 配置第一个数据源 --><bean name="dataSource_one" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value=""/><property name="url" value="$"/><property name="username" value=""/><property name="password" value=""/><!-- 初始化连接大小 --><property name="initialSize" value=""/><!-- 连接池最大使用连接数量 --><property name="maxActive" value=""/><!-- 连接池最小空闲 --><property name="minIdle" value=""/><!-- 获取连接最大等待时间 --><property name="maxWait" value=""/></bean><!-- 配置第二个数据源 --><bean name="dataSource_two" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value=""/><property name="url" value=""/><property name="username" value=""/><property name="password" value=""/><!-- 初始化连接大小 --><property name="initialSize" value=""/><!-- 连接池最大使用连接数量 --><property name="maxActive" value=""/><!-- 连接池最小空闲 --><property name="minIdle" value=""/><!-- 获取连接最大等待时间 --><property name="maxWait" value=""/></bean><!-- 多数据源配置 --><bean id="dataSource" class="com.test.datasource.manage.mybatis.DynamicDataSource"><!-- 默认使用dataSourceA的数据源 --><property name="defaultTargetDataSource" ref="dataSource_one"></property><property name="targetDataSources"><map key-type="com.test.datasource.manage.mybatis.DataSourceType"><entry key="DATASOURCE_ONE" value-ref="dataSource_one"></entry><entry key="DATASOURCE_TWO" value-ref="dataSource_two"></entry></map></property></bean><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="mapperLocations" value="classpath*:mappers/*.xml"/></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.test.datasource.manage.dao.mapper"/><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><property name="annotationClass"  value="com.test.datasource.manage.mybatis.MyBatisRepository"/>    //自己定义的mapper扫描注解 </bean><!-- AOP自动代理功能 --><aop:aspectj-autoproxy ></aop:aspectj-autoproxy>
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyBatisRepository {}

7.在mybatis的Mapper中的方法中添加注解,就可以进行数据源的动态切换:

@MyBatisRepository
public interface TestMapper {@DynamicDataSourceAnnotation(dataSource = DataSourceType.DATASOURCE_ONE)List<Entity> getEntityList(List<Integer> hids);@DynamicDataSourceAnnotation(dataSource = DataSourceType.DATASOURCE_TWO)Integer addEntityBatch(List<Entity> entityList);}   

注:动态切换数据源的注解比较灵活,可以在业务service的方法级别注解,此时需要修改aop的aspect,以便能够处理扫描到的DynamicDataSourceAnnotation,若在一个业务方法中使用到多个数据源,则需要在第一调用之后,重新获取spring的bean已获得代理对象进行数据源切换,如下:

@Component
public class TestLogic {@Autowiredprivate TestMapper testMapper;@DynamicDataSourceAnnotation(dataSource = DataSourceType.DATASOURCE_ONE)public void testMethod1(List<Integer> hids,List<Entity> entityList) {List<Entity>  list = testMapper.getEntityList(hids);getThis().addEntityBatch(entityList);}@DynamicDataSourceAnnotation(dataSource = DataSourceType.DATASOURCE_TWO)public Ingteger addEntityBatch(List<Entity> entityList){return testMapper.addEntityBatch(entityList);}private TsetLogic getThis() {return (TestLogic) SpringContextUtil.getBean(this.getClass());}
}

这种方法实现比较繁琐,个人建议直接在Mapper中的方法添加注解。

SpringAop+Mybatis 实现动态切换数据库操作相关推荐

  1. Mybatis 动态切换数据库

    mybatis介绍: 每一个Mybatis的应用程序都以一个SqlSessionFactory对象的实例为核心.SqlSessionFactory对象实例可以通过SqlSessionFactoryBu ...

  2. spring boot 入门_SpringBoot入门建站全系列(三十)Mybatis多数据源进行数据库操作

    SpringBoot入门建站全系列(三十)Mybatis多数据源进行数据库操作 一.概述 多数据源,就是有多个数据库的配置. 多数据源配置并不麻烦,使用起来和单数据源基本相同,但是,重要的是事务的控制 ...

  3. redistemplate动态切换数据库(亲测可用)

    redistemplate动态切换数据库(亲测可用)学习记录 /*** 设置数据库索引** @param dbIndex*/public void select(Integer dbIndex) {i ...

  4. springboot+redis切换指定数据库or动态切换数据库

    redis切换数据库 项目使用指定的数据库 项目中动态切换数据库 项目使用指定的数据库 需求1: 甲方有很多系统用redis,我们这个系统需要指定用到4数据库 在配置文件中设置数据库 spring:r ...

  5. springboot+mybatis实现动态切换数据源

    目前有个需求,需要使用不同的数据源,例如某业务要用A数据源,另一个业务要用B数据源. 如何在spring框架中解决多数据源的问题 使用springboot 整合多数据源 遇到的坑 1.添加依赖 < ...

  6. MyBatis执行一次数据库操作的原理以及顺序

    1.初始化SqlSessionFactory,默认实现是DefultSqlSessionFactory,这个一般是一个应用一个实例就够了,例如单例模式: 2.通过SqlSessionFactory获得 ...

  7. php 动态切换数据库,thinkphp多数据库动态切换

    thinkphp作为国内使用广泛的PHP框架,功能很强大,数据库支持方面做的也很好,并支持mongo操作,我们的项目是配置了两台数据库,一主一从,读写分离,最近要做一个活动,要求读写都在一个库上,所以 ...

  8. 利用Mybatis写第一个数据库操作的程序

    文章目录 mybatis下载 业务需求 环境搭建 加入配置文件 创建pojo sql映射文件 加载映射文件 实现根据id查询用户 测试程序: 效果 mybatis下载 mybaits的代码由githu ...

  9. 多库操作:多个数据库的动态切换(一)

    ▼ 更多精彩推荐,上午11点到达 ▼ 在平时的开发中,受到传统模式的影响,我们都是习惯了单一的数据库表操作,把数据都建到一个库里边,然后进行增删改查,这个是很经典的开发模式. 但是随着项目开发,总会出 ...

  10. Mybatis新发现—在idea中数据库操作出现了异常,最好的查错助手居然是这个!

    Mybatis新发现--如果一个数据库操作出现了异常,最好的助手居然是这样! 1. 日志工厂 如果一个数据库操作出现了异常,我们需要排错.日志就是最好的助手. 曾经:sout,debug 现在:日志工 ...

最新文章

  1. 赶考在线执业药师,7-8月提分策略,化繁为简
  2. 判断是否Ajax请求
  3. sql查询时间大于某一时间_查询时间从24分钟到2秒钟:记一次神奇的SQL优化
  4. echart 折线图设置y轴单位_如何让echarts中y轴的单位位于数值的右上角
  5. 解决ssh7.4升级8.5后环境变量失效和无法登录问题
  6. 把握人工智能命脉的有效方法
  7. linux C 基于链表链的定时器
  8. ThinkPHP框架 _ 学习3
  9. 用java编写战舰 游戏吗_如何在Java中正确建模战舰游戏
  10. 前端知识天天学(1)
  11. LSTM 文本分类模型的实现
  12. 64位window 7安装2TB以上大容量硬盘
  13. c语言基础--ASCII码表
  14. 图解通信原理与案例分析-34:车联网中的系统架构与主要的通信技术
  15. u盘linux运行速度慢,linux准确测量U盘读写速度
  16. php网页抓取浏览者手机号码_提供一个网页抓取hao123手机号码归属地的例子
  17. 批量抠图,只需要这几行python代码!
  18. sql 节假日判断(春节、中秋、国庆、周末等)
  19. 瓶子机器人diy制作大全_塑料瓶回收改造成电动机器人玩具
  20. 智慧城市建设多面手 5G智慧灯杆成为关键桥梁

热门文章

  1. c 打印二叉树_树、二叉树、二叉查找树(二叉搜索树)
  2. Java基础:Collections集合、Map集合综合案例 —— 斗地主
  3. 实战Python:详解利用Python和Pygame实现飞机大战
  4. java跳跳球代码,README.md
  5. SLAM_关于VIO中IMU预积分的讲解
  6. Ubuntu无法安装Xmind rpm包
  7. 算法笔记_面试题_12.二叉搜索树的最近公共祖先
  8. 数值分析(7)-正交多项式
  9. 安卓app开发-02-安卓app快速开发
  10. https与http的区别