返回顶部
首页 > 资讯 > 精选 >mybatisplus @DS怎么实现动态切换数据源
  • 628
分享到

mybatisplus @DS怎么实现动态切换数据源

2023-07-02 16:07:36 628人浏览 独家记忆
摘要

今天小编给大家分享一下mybatisplus @DS怎么实现动态切换数据源的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一

今天小编给大家分享一下mybatisplus @DS怎么实现动态切换数据源的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

1、mybatis-plus @DS实现动态切换数据源原理

首先mybatis-plus使用com.baomidou.dynamic.datasource.AbstractRoutingDataSource继承 AbstractDataSource接管数据源;具体实现类为com.baomidou.dynamic.datasource.DynamicRoutingDataSource。项目初始化调用public synchronized void aDDDataSource(String ds, DataSource dataSource)加载数据源,数据源存进dataSourceMap中。
private Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();

private Map<String, DynamicGroupDataSource> groupDataSources = new ConcurrentHashMap<>();public synchronized void addDataSource(String ds, DataSource dataSource) {    if (p6spy) {      dataSource = new P6DataSource(dataSource);    }    dataSourceMap.put(ds, dataSource);    if (ds.contains(UNDERLINE)) {      String group = ds.split(UNDERLINE)[0];      if (groupDataSources.containsKey(group)) {        groupDataSources.get(group).addDatasource(dataSource);      } else {        try {          DynamicGroupDataSource groupDatasource = new DynamicGroupDataSource(group,              strategy.newInstance());          groupDatasource.addDatasource(dataSource);          groupDataSources.put(group, groupDatasource);        } catch (Exception e) {          log.error("dynamic-datasource - add the datasource named [{}] error", ds, e);          dataSourceMap.remove(ds);        }      }    }    log.info("dynamic-datasource - load a datasource named [{}] success", ds);  }

进行数据操作时,方法会被com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationInterceptor拦截,

public class DynamicDataSourceAnnotationInterceptor implements MethodInterceptor {    private static final String DYNAMIC_PREFIX = "#";  private static final DynamicDataSourceClassResolver RESOLVER = new DynamicDataSourceClassResolver();  @Setter  private DsProcessor dsProcessor;  @Override  public Object invoke(MethodInvocation invocation) throws Throwable {    try {      DynamicDataSourceContextHolder.push(determineDatasource(invocation));      return invocation.proceed();    } finally {      DynamicDataSourceContextHolder.poll();    }  }  private String determineDatasource(MethodInvocation invocation) throws Throwable {    Method method = invocation.getMethod();    DS ds = method.isAnnotationPresent(DS.class)        ? method.getAnnotation(DS.class)        : AnnotationUtils.findAnnotation(RESOLVER.targetClass(invocation), DS.class);    String key = ds.value();    return (!key.isEmpty() && key.startsWith(DYNAMIC_PREFIX)) ? dsProcessor        .determineDatasource(invocation, key) : key;  }}

拦截器首先从被拦截的方法或者类(一般@DS注解用于Service,也可用于Mapper和Controller)上寻找@DS注解,获取到@DS注解的值后将其存入com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;DynamicDataSourceContextHolder使用ThreadLocal存储当前线程的数据源名。

public final class DynamicDataSourceContextHolder {    @SuppressWarnings("unchecked")  private static final ThreadLocal<Deque<String>> LOOKUP_KEY_HOLDER = new ThreadLocal() {    @Override    protected Object initialValue() {      return new ArrayDeque();    }  };  private DynamicDataSourceContextHolder() {  }    public static String peek() {    return LOOKUP_KEY_HOLDER.get().peek();  }    public static void push(String ds) {    LOOKUP_KEY_HOLDER.get().push(StringUtils.isEmpty(ds) ? "" : ds);  }    public static void poll() {    Deque<String> deque = LOOKUP_KEY_HOLDER.get();    deque.poll();    if (deque.isEmpty()) {      LOOKUP_KEY_HOLDER.remove();    }  }    public static void clear() {    LOOKUP_KEY_HOLDER.remove();  }}

进行数据操作时,会调用org.springframework.jdbc.datasource.getConnection()方法;getConnection()方法最终调用了com.baomidou.dynamic.datasource.AbstractRoutingDataSource的getConnection()方法;

  @Override  public Connection getConnection() throws sqlException {    return determineDataSource().getConnection();  }

determineDataSource()由子类com.baomidou.dynamic.datasource.DynamicRoutingDataSource实现,可以看到DynamicRoutingDataSource从DynamicDataSourceContextHolder获取数据源名称,这个在之前拦截器处理存进ThreadLocal中,如果有数据源名称则从dataSourceMap中获取,没有则获取默认的primary数据源。

public DataSource determineDataSource() {    return getDataSource(DynamicDataSourceContextHolder.peek());}public DataSource getDataSource(String ds) {    if (StringUtils.isEmpty(ds)) {        return determinePrimaryDataSource();    } else if (!groupDataSources.isEmpty() && groupDataSources.containsKey(ds)) {        log.debug("dynamic-datasource switch to the datasource named [{}]", ds);        return groupDataSources.get(ds).determineDataSource();    } else if (dataSourceMap.containsKey(ds)) {        log.debug("dynamic-datasource switch to the datasource named [{}]", ds);        return dataSourceMap.get(ds);    }    if (strict) {        throw new RuntimeException("dynamic-datasource could not find a datasource named" + ds);    }    return determinePrimaryDataSource();}private DataSource determinePrimaryDataSource() {    log.debug("dynamic-datasource switch to the primary datasource");    return groupDataSources.containsKey(primary) ? groupDataSources.get(primary)        .determineDataSource() : dataSourceMap.get(primary);}

此时的数据源已经切换成了我们需要的数据源。

数据操作完成后,方法返回第二步中的拦截器,执行DynamicDataSourceContextHolder.poll();清除掉此次的数据源,避免影响后续数据操作。

附上动态数据源相关配置

spring:  application:    name:   datasource:    dynamic:      primary: dataSource1      datasource:        dataSource1:          type: com.alibaba.druid.pool.DruidDataSource          driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver          url: jdbc:sqlserver://localhost:1433;database=dataSource1          username:           passWord:         dataSource2:          type: com.alibaba.druid.pool.DruidDataSource          driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver          url: jdbc:sqlserver://localhost:1433;instanceName=sqlserver2017;DatabaseName=dataSource2          username:           password:

pom.xml

<dependency>    <groupId>com.baomidou</groupId>    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>    <version>2.5.6</version></dependency>

相应类

@Service//@DS("dataSource2") 放在类上就是类下所有方法都使用这个数据源。public class XXXServiceImpl extends BaseServiceImpl<XXXMapper, XXXBean> implements XXXService {    @DS("dataSource1")    public void selectDataFromSource1() {       // do somethinng;    }        @DS("dataSource2")    public void selectDataFromSource1() {       // do somethinng;    }}

**注意:**不可在事务中切换数据库,保证事务需要方法使用同一连接,使用@DS(dataSource1)方法调用@DS(dataSource2)无法切换连接,会导致方法报错。

以上就是“mybatisplus @DS怎么实现动态切换数据源”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网精选频道。

--结束END--

本文标题: mybatisplus @DS怎么实现动态切换数据源

本文链接: https://lsjlt.com/news/343053.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • mybatisplus @DS怎么实现动态切换数据源
    今天小编给大家分享一下mybatisplus @DS怎么实现动态切换数据源的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一...
    99+
    2023-07-02
  • mybatis-plus@DS实现动态切换数据源原理
    1、mybatis-plus @DS实现动态切换数据源原理 首先mybatis-plus使用com.baomidou.dynamic.datasource.AbstractRouti...
    99+
    2024-04-02
  • java动态数据源切换怎么实现
    在Java中实现动态数据源切换有多种方式,以下是其中一种常见的实现方法:1. 创建一个数据源容器类:创建一个类来管理多个数据源对象,...
    99+
    2023-10-09
    java
  • Springboot动态切换数据源怎么实现
    这篇文章主要介绍“Springboot动态切换数据源怎么实现”,在日常操作中,相信很多人在Springboot动态切换数据源怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Springboot动态切换数...
    99+
    2023-06-25
  • springboot怎么集成@DS注解实现数据源切换
    这篇文章主要介绍“springboot怎么集成@DS注解实现数据源切换”,在日常操作中,相信很多人在springboot怎么集成@DS注解实现数据源切换问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”sprin...
    99+
    2023-06-29
  • Spring多数据源AOP动态切换怎么实现
    这篇文章主要讲解了“Spring多数据源AOP动态切换怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring多数据源AOP动态切换怎么实现”吧!一:新增多数据源类public c...
    99+
    2023-06-04
  • Spring AOP实现多数据源动态切换
    目录需求背景分析及实现配置多数据源信息Spring如何获取配置好的多个数据源信息?Spring如何选择使用数据源?结语需求背景 去年底,公司项目有一个需求中有个接口需要用到平台、算法...
    99+
    2024-04-02
  • springboot+dynamicDataSource怎么实现动态添加切换数据源
    今天小编给大家分享一下springboot+dynamicDataSource怎么实现动态添加切换数据源的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,...
    99+
    2023-06-26
  • 详解SpringBoot+Mybatis实现动态数据源切换
    业务背景 电商订单项目分正向和逆向两个部分:其中正向数据库记录了订单的基本信息,包括订单基本信息、订单商品信息、优惠卷信息、发票信息、账期信息、结算信息、订单备注信息、收货人信息等...
    99+
    2024-04-02
  • springboot中mybatis多数据源动态切换实现
    目录多数据源配置引入 动态数据源路由实现 动态数据源切换使用 案例源码 在开发中,动态数据源配置还是用的比较多的,比如在多数据源使用方面,又或者是在多个DB之间切换方面。这里给出一个...
    99+
    2024-04-02
  • SpringBoot+Mybatis如何实现动态数据源切换
    这篇文章主要介绍了SpringBoot+Mybatis如何实现动态数据源切换,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。springboot是什么springboot一种全...
    99+
    2023-06-14
  • Springboot实现根据用户ID切换动态数据源
    首先在application.yml 文件添加一下配置  #每个库可连接最大用户数 dynamic-server: #每个服务最大建库数 database-max-num...
    99+
    2024-04-02
  • Jdbc怎么实现分布式事务数据源动态切换
    本篇内容介绍了“Jdbc怎么实现分布式事务数据源动态切换”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一:依赖的jar包  Mav...
    99+
    2023-06-04
  • 【Java多数据源实现教程】实现动态数据源、多数据源切换方式
    前言 本文为 【Java多数据源实现教程】 相关知识,由于自己最近在做导师的项目的时候需要使用这种技术,于是自学了相关技术原理与实现,并将其整理如下,具体包含:多数据源的典型使用场景(包含业务复杂场景、读写分离场景),多数据源实现原理及实...
    99+
    2023-08-16
    java mybatis spring
  • SpringBoot基于AbstractRoutingDataSource实现多数据源动态切换
    目录一、场景二、原理三、代码示例一、场景 在生产业务中,有一些任务执行了耗时较长的查询操作,在实时性要求不高的时候,我们希望将这些查询sql分离出来,去从库查询,以减少应用对主数据库...
    99+
    2024-04-02
  • MyBatisPlus怎么集成动态多数据源
    本篇内容主要讲解“MyBatisPlus怎么集成动态多数据源”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MyBatisPlus怎么集成动态多数据源”吧!这里使用的是dynamic-dataso...
    99+
    2023-07-02
  • springboot集成@DS注解实现数据源切换的方法示例
    目录启用@DS实现数据源切换POM内添加核心jar包yml配置“核心”-使用@DS注解最后启用@DS实现数据源切换 POM内添加核心jar包         ...
    99+
    2024-04-02
  • Java注解实现动态数据源切换的实例代码
    当一个项目中有多个数据源(也可以是主从库)的时候,我们可以利用注解在mapper接口上标注数据源,从而来实现多个数据源在运行时的动态切换。实现原理在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充...
    99+
    2023-05-31
    java 数据源 切换
  • SpringBoot基于AbstractRoutingDataSource如何实现多数据源动态切换
    本文小编为大家详细介绍“SpringBoot基于AbstractRoutingDataSource如何实现多数据源动态切换”,内容详细,步骤清晰,细节处理妥当,希望这篇“SpringBoot基于AbstractRoutingDataSour...
    99+
    2023-06-30
  • SpringBoot多数据源配置并通过注解实现动态切换数据源
    目录1. 环境准备1.1 数据库准备1.2 项目创建2. ThreadLocal类介绍3. AbstractRoutingDataSource类介绍4. 具体实现4.1 定义数据源枚...
    99+
    2022-11-13
    SpringBoot 动态切换数据源 SpringBoot 切换数据源
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作