项目中将一个库的某些标的某些数据保存到另一个库。

使用spring的aop编程动态切换数据源,代码如下,以备下次用到!

1.先将两个数据库连接,创建两个数据源,交于spring管理!

<bean id="dataSource"
class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean> <bean id="dataSource2"
class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>

2.将动态切换数据源的类交给spring

    <bean id="dynamicDataSource" class="cn.**.**.common.db.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<!-- 指定lookupKey和与之对应的数据源 -->
<entry key="dataSource" value-ref="dataSource"></entry>
<entry key="dataSource2" value-ref="dataSource2"></entry>
</map>
</property>
<!-- 这里可以指定默认的数据源 -->
<property name="defaultTargetDataSource" ref="dataSource" />
</bean>

3.创建数据源切换的类,必须继承 AbstractRoutingDataSource 这个类(数据源动态切换必须继承该类)

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
protected Object determineCurrentLookupKey() {
// 从自定义的位置获取数据源标识
return DynamicDataSourceHolder.getDataSource();
} }

4.将数据源放进线程中,避免相互干扰

public class DynamicDataSourceHolder {

    /**
* 注意:数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰
*/
private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal<String>(); public static String getDataSource() {
String dataSource = THREAD_DATA_SOURCE.get();
if(StringUtils.isEmpty(dataSource)){
return DataSourceKey.DATA_SOURCE;
}else{
return dataSource;
}
} public static void setDataSource(String dataSource) {
THREAD_DATA_SOURCE.set(dataSource);
} public static void clearDataSource() {
THREAD_DATA_SOURCE.remove();
} }

5.数据源的key

DataSourceKey 这个类是多个数据源在spring管理中的name标识,可通过key取得数据源。

6.设置默认的数据源。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource { /**
* 默认是某个数据源
*/
String value() default DataSourceKey.DATA_SOURCE; }

7.根据spring的aop在执行之前将数据源放进线程中,动态切换数据源。

@Aspect
@Component
@Order(0)
public class DataSourceAspect{ private Logger logger = Logger.getLogger(getClass()); @Pointcut("execution(public * cn.**.**.service..*Service.*(..))")
public void dataSourceAspect(){}; /**
* 拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源
*/
@Before("dataSourceAspect()")
public void before(JoinPoint point) throws Exception{
Class<?> target = point.getTarget().getClass();
MethodSignature signature = (MethodSignature) point.getSignature();
// 默认使用目标类型的注解,如果没有则使用其实现接口的注解
for (Class<?> clazz : target.getInterfaces()) {
resolveDataSource(clazz, signature.getMethod());
}
resolveDataSource(target, signature.getMethod());
} private void resolveDataSource(Class<?> clazz, Method method) {
try {
Class<?>[] types = method.getParameterTypes();
// 先使用类型注解
if (clazz.isAnnotationPresent(DataSource.class)) {
DataSource source = clazz.getAnnotation(DataSource.class);
DynamicDataSourceHolder.setDataSource(source.value());
}else{
DynamicDataSourceHolder.clearDataSource();
}
// 方法注解可以覆盖类型注解
Method m = clazz.getMethod(method.getName(), types);
if (m != null && m.isAnnotationPresent(DataSource.class)) {
DataSource source = m.getAnnotation(DataSource.class);
DynamicDataSourceHolder.setDataSource(source.value());
}
logger.info("选择连接加载的DB :"+DynamicDataSourceHolder.getDataSource());
} catch (Exception e) {
//如果出现异常不能断了所有连接,默认还是某个数据库连接
logger.error("选择连接加载DB ERROR "+clazz+":" +e.getMessage());
}
}
}

8.service层动态切换

默认的数据源不用标明,另一个数据源用@DataSource(DataSourceKey.LYD_DATA_SOURCE) 在service上标明即可。

9.另一个库的查询也可用@Results注解封装返回的实体(或map),sql用@Select注解

10.在多数据源切换中,不要在一个事务方法里面用到两个数据源,不然会切换不过去。因为事务一般定义在service层,所以如果用到两个数据源,可以将两个数据源放在controller进行。

mybatis多数据库切换,(动态数据源)。的更多相关文章

  1. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_3-1.整合Mybatis访问数据库和阿里巴巴数据源

    笔记 1.整合Mybatis访问数据库和阿里巴巴数据源     简介:整合mysql 加入mybatis依赖,和加入alibaba druid数据源 1.加入依赖(可以用 http://start.s ...

  2. mybatis用spring的动态数据源实现读写分离

    一.环境: 三个mysql数据库.一个master,两个slaver.master写数据,slaver读数据. 二.原理: 借助Spring的 AbstractRoutingDataSource 这个 ...

  3. Spring Boot + Mybatis + Druid 动态切换多数据源

    在大型应用程序中,配置主从数据库并使用读写分离是常见的设计模式. 在Spring应用程序中,要实现读写分离,最好不要对现有代码进行改动,而是在底层透明地支持. 这样,就需要我们再一个项目中,配置两个, ...

  4. SpringBoot+Mybatis 实现动态数据源切换方案

    背景 最近让我做一个大数据的系统,分析了一下,麻烦的地方就是多数据源切换抽取数据.考虑到可以跨服务器跨数据库抽数,再整理数据,就配置了这个动态数据源的解决方案.在此分享给大家. 实现方案 数据库配置文 ...

  5. Spring主从数据库的配置和动态数据源切换原理

    原文:https://www.liaoxuefeng.com/article/00151054582348974482c20f7d8431ead5bc32b30354705000 在大型应用程序中,配 ...

  6. Spring-Boot 多数据源配置+动态数据源切换+多数据源事物配置实现主从数据库存储分离

    一.基础介绍 多数据源字面意思,比如说二个数据库,甚至不同类型的数据库.在用SpringBoot开发项目时,随着业务量的扩大,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源. ...

  7. 如何通过Spring Boot配置动态数据源访问多个数据库

    之前写过一篇博客<Spring+Mybatis+Mysql搭建分布式数据库访问框架>描述如何通过Spring+Mybatis配置动态数据源访问多个数据库.但是之前的方案有一些限制(原博客中 ...

  8. Spring动态切换多数据源解决方案

    Spring动态配置多数据源,即在大型应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性.而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时 ...

  9. AbstractRoutingDataSource实现动态数据源切换 专题

    需求:系统中要实现切换数据库(业务数据库和his数据库) 网上很多资料上有提到AbstractRoutingDataSource,大致是这么说的 在Spring 2.0.1中引入了AbstractRo ...

随机推荐

  1. [LeetCode] 622.Design Circular Queue 设计环形队列

    Design your implementation of the circular queue. The circular queue is a linear data structure in w ...

  2. 1-4dockerfile基本使用

    1.创建一个文件夹 mkdir mynginx cd mynginx touch Dockerfile [root@VM_0_10_centos mynginx]# cat Dockerfile FR ...

  3. linux中C语言的运行(gcc)

    执行sudo apt-get install build-essential 出现

  4. python学习-32 zip函数

    zip 拉链方法 例如:1. ')))) 运行结果: [(')] Process finished with exit code 0 2. a = {'name':'abc','age':18,'ad ...

  5. Python之路【第十一篇】:Python面向对象之封装

    一 引子 从封装本身的意思去理解,封装就好像是拿来一个麻袋,把青菜,土豆,花菜,还有苹果一起装进麻袋,然后把麻袋封上口子.照这种逻辑看,封装=‘隐藏’,这种理解是相当片面的. 在面向对象中这个麻袋就是 ...

  6. vue的特殊指令 v-if v-once v-bind v-for v-on v-model

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 记录个超级Update语句

    -- UPDATE UPDATE affair_list SET deleteState = WHERE gid IN ( SELECT tt.gid FROM ( SELECT a.gid FROM ...

  8. Redis笔记01——win10 64位系统安装Redis 3.2.100

    前言 由于项目中需要用到Redis,所以先在自己的win10上安装来体验一下. 安装步骤 一.下载地址 Redis下载地址 我选择的是3.2.100 的 64位 zip版本 二.安装位置以及文件简介 ...

  9. np.any()基本用法与不一样环境中的用法

    import numpy as npa=np.ones((2,3,4))b=np.array([1,2,3])c=b<2k=np.any(c) # 是或的关系,只要有一个满足,则输出为TRUEp ...

  10. aria2 添加任务后一直在等待,不进行下载是什么情况?

    https://www.v2ex.com/t/567014 跑 aria2 的机器配置比较低,是 j1900+4G 的小机器,系统是 ubuntu18.04 ,所有的任务都是 bt 下载.aria2 ...