前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring Boot 中 Druid 连接池与多数据源切换的方法

Spring Boot 中 Druid 连接池与多数据源切换的方法

作者头像
公众号:码到三十五
发布于 2024-11-18 00:21:06
发布于 2024-11-18 00:21:06
22800
代码可运行
举报
文章被收录于专栏:设计模式设计模式
运行总次数:0
代码可运行

❃博主首页 : 「码到三十五」 ,同名公众号 :「码到三十五」,wx号 : 「liwu0213」 ☠博主专栏 : <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 : 搬的每块砖,皆为峰峦之基;公众号搜索「码到三十五」关注这个爱发技术干货的coder,一起筑基

微服务架构中多数据源切换是个常见的需求。Spring Boot 提供了强大的支持来简化这一过程.

多数据源切换原理

多数据源切换的原理主要基于 Spring 的 AbstractRoutingDataSource 类。AbstractRoutingDataSource 类允许根据运行时上下文动态选择数据源。其核心在于实现 determineCurrentLookupKey 方法,该方法决定当前操作使用哪个数据源。 AbstractRoutingDataSource 实现多数据源切换的原理:

1. 数据源映射
  • AbstractRoutingDataSource 内部维护了一个映射(Map),用于存储数据源标识(key)和对应的数据源实例(value)。这个映射允许根据数据源标识快速查找和获取对应的数据源。
2. 数据源标识的确定
  • AbstractRoutingDataSource 提供了一个抽象方法 determineCurrentLookupKey(),该方法用于确定当前需要使用的数据源标识。这个方法需要由子类实现,以返回当前线程或请求应该使用的数据源标识。
3. 数据源的选择与连接获取
  • 当应用程序需要获取数据库连接时,AbstractRoutingDataSourcegetConnection() 方法会被调用。这个方法首先调用 determineCurrentLookupKey() 方法来获取当前的数据源标识,然后根据这个标识从内部映射中查找对应的数据源。
  • 一旦找到了对应的数据源,AbstractRoutingDataSource 就会调用该数据源的 getConnection() 方法来获取实际的数据库连接,并将这个连接返回给应用程序。
4. 数据源切换的实现
  • 为了实现数据源的动态切换,通常会在子类中重写 determineCurrentLookupKey() 方法,并根据当前的上下文(如线程变量)来确定返回的数据源标识。
  • 此外,通常会使用 ThreadLocal 来存储每个线程的数据源标识,这样每个线程都可以独立地切换数据源而不会互相干扰。
实现步骤
1. 依赖

引入 MySQL 和 Druid 的依赖

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.6</version>
</dependency>
2. 配置数据源

application.yml 文件中配置多个数据源。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      datasource1:
        url: jdbc:mysql://localhost:3306/master_db
        username: root
        password: password
        initial-size: 5
        min-idle: 5
        max-active: 20
        max-wait: 60000
      datasource2:
        url: jdbc:mysql://localhost:3306/slave_db
        username: root
        password: password
        initial-size: 5
        min-idle: 5
        max-active: 20
        max-wait: 60000
3. 创建数据源配置类

创建一个配置类来定义数据源 Bean。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Configuration
public class DataSourceConfig {

    @Bean
    @ConditionalOnProperty(prefix = "spring.datasource.druid", name = "datasource1")
    @ConfigurationProperties(prefix = "spring.datasource.druid.datasource1")
    public DataSource dataSource1() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConditionalOnProperty(prefix = "spring.datasource.druid", name = "datasource2")
    @ConfigurationProperties(prefix = "spring.datasource.druid.datasource2")
    public DataSource dataSource2() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setDefaultTargetDataSource(dataSource1());
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("dataSource1", dataSource1());
        targetDataSources.put("dataSource2", dataSource2());
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }
}
4. 实现 AbstractRoutingDataSource

创建一个继承自 AbstractRoutingDataSource 的类,并实现 determineCurrentLookupKey 方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSource();
    }
}
5. 创建 DataSourceContextHolder

创建一个工具类来保存当前线程的数据源信息。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DataSourceContextHolder {

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

    public static void setDataSource(String dataSource) {
        CONTEXT_HOLDER.set(dataSource);
    }

    public static String getDataSource() {
        return CONTEXT_HOLDER.get();
    }

    public static void clearDataSource() {
        CONTEXT_HOLDER.remove();
    }
}
6. AOP动态切换数据源

使用 AOP 在方法执行前后切换数据源。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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.springframework.stereotype.Component;

@Aspect
@Component
public class DataSourceAspect {
	// 方法或者类上的横切点
    @Pointcut("@annotation(dataSource) || @within(dataSource)")
    public void dataSourcePointcut(DataSource dataSource) {}

    @Before("dataSourcePointcut(dataSource)")
    public void switchDataSource(JoinPoint joinPoint, DataSource dataSource) {
        // 从注解中获取数据源标识
        String dataSourceKey = dataSource.value();
        // 切换到指定的数据源
        DataSourceContextHolder.setDataSourceType(dataSourceKey);
    }

    @AfterReturning(pointcut = "dataSourcePointcut(dataSource)", returning = "result")
    public void restoreDataSource(JoinPoint joinPoint, DataSource dataSource, Object result) {
        // 恢复默认数据源(可选)
        DataSourceContextHolder.clearDataSourceType();
    }
}

/**
* 自定义注解
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {

    String value() default "dataSource1";
}
7. 使用自定义注解

在需要切换数据源的方法上使用自定义注解。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Service
public class UserService {

    @Autowired
    private UserRepository userRepo;

    @DataSource("dataSource2")
    public void queryAndUpdate(List<Integer> deptIds) {
        List<User> userList = userRepo.findAll();
        System.out.println(userList.size());
        // 其他操作
    }
}
注意
  • 数据源切换的逻辑应该尽可能简单和高效,以避免对应用程序性能产生负面影响。
  • 在切换数据源时,需要注意事务管理的问题,确保在同一个事务中只使用同一个数据源。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-11-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
SpringBoot动态切换多数据源
最常见的单一应用中最多涉及到一个数据库,即是一个数据源(Datasource)。那么顾名思义,多数据源就是在一个单一应用中涉及到了两个及以上的数据库了。
Ant丶
2022/08/31
1.7K0
SpringBoot 实现动态切换数据源,这样做才更优雅!
最近在做业务需求时,需要从不同的数据库中获取数据然后写入到当前数据库中,因此涉及到切换数据源问题。本来想着使用Mybatis-plus中提供的动态数据源SpringBoot的starter:dynamic-datasource-spring-boot-starter来实现。
良月柒
2023/12/13
5.8K0
SpringBoot 实现动态切换数据源,这样做才更优雅!
【详解】JavaSpringMVC+MyBitis+多数据源切换
在企业级应用开发中,经常需要处理来自不同数据库的数据。为了满足这一需求,我们可以通过配置多个数据源来实现对不同数据库的访问。本文将介绍如何在Spring MVC框架下结合MyBatis实现多数据源的动态切换。
大盘鸡拌面
2025/01/19
1600
Spring项目中使用两种方法动态切换数据源,多数据源切换
本文介绍两种动态切换数据库的方法。 方法一:数据源信息配置在xml中,适用于一般数据库切换。执行完某操作,切换数据库,执行另一个操作。 方法二:数据源信息配置在默认数据源中,适用于切换数据库操作同一方法,相当于批量执行方法。
Java架构师历程
2020/02/25
2.4K0
Spring Boot + Mybatis多数据源和动态数据源配置
转载自 http://blog.csdn.net/neosmith/article/details/61202084
allsmallpig
2021/02/25
1.3K0
Spring MyBatis多数据源(同包)
创建基本的包 entity service dao 为了区分多数据源 一个用的是Mysql 一个是Oracle 方便测试,
試毅-思伟
2018/09/06
1K0
Spring MyBatis多数据源(同包)
Spring Boot中实现多数据源连接和切换的方案
在Spring Boot中,通过AbstractRoutingDataSource实现多数据源连接是一种常见的做法。这种技术允许你在运行时动态地切换数据源,从而支持对多个数据库的操作。Spring Boot中配置和使用AbstractRoutingDataSource来实现多数据源连接。
公众号:码到三十五
2024/11/04
6700
SpringBoot Jpa 多数据源动态切换
在大型应用程序中,配置主从数据库并使用读写分离是常见的设计模式。常用的实现方式是使用数据库中间件,此文介绍如何通过编写代码的方式实现多数据源的配置和动态切换。核心是使用Spring 内置的 AbstractRoutingDataSource 这个抽象类,它可以把多个数据源配置成一个Map,然后,根据不同的key返回不同的数据源。
BUG弄潮儿
2022/02/10
1.5K0
项目要实现多数据源动态切换,咋搞?
在做项目的时候,几乎都会用到数据库,很多时候就只连一个数据库,但是有时候我们需要一个项目操作多个数据库,不同的业务功能产生的数据存到不同的数据库,那怎么来实现数据源的动态、灵活的切换呢?今天我们就来实现这个功能。
编程大道
2020/10/10
1.3K0
项目要实现多数据源动态切换,咋搞?
SpringBoot整合多数据源
我们在调用任何持久层的框架,都是基于JDBC进行操作的,只要集成了Spring框架就一定会注入配置的DataSource获取连接dataSource.getConnection()。既然是我们配置的,我们可以实现一个自定义的DataSource,然后动态提供数据源。说干就干
别团等shy哥发育
2024/05/24
1.7K1
SpringBoot整合多数据源
使用springboot + druid + mybatisplus完成多数据源配置「建议收藏」
大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说使用springboot + druid + mybatisplus完成多数据源配置「建议收藏」,希望能够帮助大家进步!!!
Java架构师必看
2022/02/10
4.2K0
使用springboot + druid + mybatisplus完成多数据源配置「建议收藏」
Spring多数据源配置系列(一)——多数据源配置
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
逝兮诚
2019/10/30
2.1K0
Spring Boot MyBatis 动态数据源切换、多数据源,读写分离
项目地址: https://github.com/helloworlde/SpringBoot-DynamicDataSource
JAVA葵花宝典
2019/06/11
2K0
SpringBoot 多数据源及事务解决方案
一个主库和N个应用库的数据源,并且会同时操作主库和应用库的数据,需要解决以下两个问题:
码猿技术专栏
2023/05/01
1.3K0
SpringBoot 多数据源及事务解决方案
spring配置多数据源——mybatis
这篇文章是配置mybatis多数据源文章,如果是hibernate的话也是没什么影响,配置都是差不多的。
陈灬大灬海
2022/11/23
2760
3种方式实现多数据源控制/切换、实现读写分离;演示借助AbstractRoutingDataSource实现多数据源的动态切换代码【享学Spring】
什么时候一个Java工程里需要同时控制(连接)多个数据源呢?我认为主要有如下两种情况:
YourBatman
2019/09/03
9.5K1
3种方式实现多数据源控制/切换、实现读写分离;演示借助AbstractRoutingDataSource实现多数据源的动态切换代码【享学Spring】
SpringBoot+AOP构建多数据源的切换实践
针对微服务架构中常用的设计模块,通常我们都会需要使用到druid作为我们的数据连接池,当架构发生扩展的时候 ,通常面对的数据存储服务器也会渐渐增加,从原本的单库架构逐渐扩展为复杂的多库架构。
哲洛不闹
2020/06/04
5610
spring-boot使用aop进行多数据源切换
创建一个spring boot项目,并引入druid mysql aop等相关依赖
earthchen
2020/09/24
1.2K0
基于注解多数据源解决方案
前一段时间研究了一下spring多数据源的配置和使用,为了后期从多个数据源拉取数据定时进行数据分析和报表统计做准备。由于之前做过的项目都是单数据源的,没有遇到这种场景,所以也一直没有去了解过如何配置多数据源。 后来发现其实基于spring来配置和使用多数据源还是比较简单的,因为spring框架已经预留了这样的接口可以方便数据源的切换。 先看一下spring获取数据源的源码:
yaphetsfang
2020/07/30
6170
基于注解多数据源解决方案
Spring Boot2.x 动态数据源配置
基于 Spring Boot 2.x、Spring Data JPA、druid、mysql 的动态数据源配置Demo,适合用于数据库的读写分离等应用场景。通过在Service层方法上添加自定义注解实现读写不同的数据库。
壹言
2020/03/01
1.4K0
Spring Boot2.x 动态数据源配置
推荐阅读
相关推荐
SpringBoot动态切换多数据源
更多 >
LV.1
公众号:码到三十五公众号:【码到三十五】
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验