springboot动态数据源切换

news/2024/11/17 22:24:21/

1)、就是将多个数据源全部注入到bean中,根据需要实现多数据源之间的切换。
2)、使用baomidou的@DS注解。见文章@DS注解实现数据源动态切换


com.baomidou
dynamic-datasource-spring-boot-starter
3.5.1

##设置默认的数据源或者数据源组,默认值即为master
spring.datasource.dynamic.primary=master
#设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
spring.datasource.dynamic.strict=false

postgresql 配置 主库的配置

spring.datasource.dynamic.datasource.master.url = jdbc:postgresql://localhost:5432/zhejiang_data_repository
spring.datasource.dynamic.datasource.master.username=root
spring.datasource.dynamic.datasource.master.password=root
spring.datasource.dynamic.datasource.master.driver-class-name=org.postgresql.Driver
#从库的配置
spring.datasource.dynamic.datasource.slave.url = jdbc:postgresql://localhost:5432/server_test_logdb
spring.datasource.dynamic.datasource.slave.username=postgres
spring.datasource.dynamic.datasource.slave.password=123456
spring.datasource.dynamic.datasource.slave.driver-class-name=org.postgresql.Driver
使用@DS(“slave”)注解在类或者方法,同时使用方式上优先类上

1.配置文件配置多个数据库连接
#主库
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:postgresql://localhost:5432/sgeoc_sec_system
spring.datasource.username=postgres
spring.datasource.password=123456
spring.datasource.driver-class-name=org.postgresql.Driver

#从库
spring.slave-datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.slave-datasource.url=jdbc:postgresql://localhost:5432/server_test_system
spring.slave-datasource.username=postgres
spring.slave-datasource.password=123456
spring.slave-datasource.driver-class-name=org.postgresql.Driver

2.注入数据源
将配置的数据源全部注入到bean中,可以设置默认的数据源,也可以动态设置系统使用的数据源。
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**

  • 数据源注入

  • @author yjj

  • @version 1.0

  • @since 2022 -08-29 09:50:30
    /
    @Slf4j
    @Configuration
    public class DataSourceConfig {
    /
    *

    • 主库数据源bean名称
      /
      public static final String MASTER_DATASOURCE = “masterDataSource”;
      /
      *
    • 从库数据源bean名称
      */
      public static final String SLAVE_DATASOURCE = “slaveDataSource”;

    /**

    • 主库数据源对象bean生成
    • @param properties 配置项
    • @return DruidDataSource
      */
      @Bean(MASTER_DATASOURCE)
      @ConfigurationProperties(prefix = “spring.datasource”)
      public DruidDataSource masterDataSource(DataSourceProperties properties) {
      DruidDataSource build = properties.initializeDataSourceBuilder().type(DruidDataSource.class).build();
      log.info(“配置主数据库:{}”, build);
      return build;
      }

    /**

    • 从库数据源对象bean生成
    • @param properties 配置项
    • @return DruidDataSource
      */
      @Bean(SLAVE_DATASOURCE)
      @ConfigurationProperties(prefix = “spring.slave-datasource”)
      public DruidDataSource slaveDataSource(DataSourceProperties properties) {
      DruidDataSource build = properties.initializeDataSourceBuilder().type(DruidDataSource.class).build();
      log.info(“配置从数据库:{}”, build);
      return build;
      }

    /**

    • 数据源配置
    • @param masterDataSource 主库数据源对象
    • @param slaveDataSource 从库数据源对象
    • @return DataSource
    • @Primary 优先使用这个DataSource对象bean
      /
      @Bean
      @Primary
      @DependsOn(value = {MASTER_DATASOURCE, SLAVE_DATASOURCE})
      public DataSource routingDataSource(@Qualifier(MASTER_DATASOURCE) DruidDataSource masterDataSource,
      @Qualifier(SLAVE_DATASOURCE) DruidDataSource slaveDataSource) {
      if (StringUtils.isBlank(slaveDataSource.getUrl())) {
      log.info(“没有配置从数据库,默认使用主数据库”);
      return masterDataSource;
      }
      Map<Object, Object> map = new HashMap<>();
      map.put(DataSourceConfig.MASTER_DATASOURCE, masterDataSource);
      map.put(DataSourceConfig.SLAVE_DATASOURCE, slaveDataSource);
      DynamicDataSource routing = new DynamicDataSource();
      //设置动态数据源
      routing.setTargetDataSources(map);
      //设置默认数据源
      routing.setDefaultTargetDataSource(masterDataSource);
      log.info(“主从数据库配置完成”);
      return routing;
      }
      }

      @Configuration
      public class DataSourceConfig {
      /
      *
    • 数据源1配置
      */
      @Bean(“ds1”)
      @ConfigurationProperties(“spring.datasource.ds1”)
      public DataSource ds1() {
      return DataSourceBuilder.create().build();
      }

    /**

    • 数据源2配置
      */
      @Bean(“ds2”)
      @ConfigurationProperties(“spring.datasource.ds2”)
      public DataSource ds2() {
      return DataSourceBuilder.create().build();
      }

    /**

    • 动态数据源配置
      */
      @Bean
      @Primary
      public DataSource dynamicDataSource(@Qualifier(“ds1”) DataSource ds1, @Qualifier(“ds2”) DataSource ds2) {
      DynamicDataSource ds = new DynamicDataSource();
      // 设置数据源映射关系
      ds.setTargetDataSources(Map.of(
      “ds1”, ds1,
      “ds2”, ds2
      ));
      // 设置默认数据源
      ds.setDefaultTargetDataSource(ds1);
      return ds;
      }
      }

3.实现数据源动态切换
import com.southsmart.sso.util.DataSourceUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**

  • 动态数据源
  • @author yjj
  • @version 1.0
  • @since 2022 -08-29 09:55:26
    */
    @Slf4j
    public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
    String db = DataSourceUtil.getDb();
    log.info(“使用数据源:{}”, db);
    return db;
    }
    }

4.切换数据源管理类
/**

  • 数据源切换工具

  • @author yjj

  • @version 1.0

  • @since 2022 -08-29 09:54:05
    /
    public class DataSourceUtil {
    /
    *

    • 数据源属于一个公共的资源
    • 采用ThreadLocal可以保证在多线程情况下线程隔离
      */
      private static final ThreadLocal contextHolder = new ThreadLocal<>();

    /**

    • 设置数据源名
    • @param dbType the db type
      */
      public static void setDb(String dbType) {
      contextHolder.set(dbType);
      }

    /**

    • 获取数据源名
    • @return db
      */
      public static String getDb() {
      return (contextHolder.get());
      }

    /**

    • 清除数据源名
      */
      public static void clearDb() {
      contextHolder.remove();
      }
      }
      5.添加自定义注解Db,标注在方法上,指定方法内部执行时所使用的数据源
      @Target(ElementType.METHOD)
      @Retention(RetentionPolicy.RUNTIME)
      public @interface Db {
      String value();
      }

6.现切面类DynamicDataSourceAspect,对所有标注了Db注解的方法进行增强
@Aspect
@Component
public class DynamicDataSourceAspect {
/**
* Mapper方法切面实现,对所有标注了Db注解的方法生效
*/
@Around(“@annotation(byx.test.Db)”)
public Object around(ProceedingJoinPoint jp) throws Throwable {
// 获取方法上的Db注解
MethodSignature methodSignature = (MethodSignature) jp.getSignature();
Method method = methodSignature.getMethod();
Db db = method.getAnnotation(Db.class);

    try {// 方法执行前先设置当前数据源,再执行方法DataSourceHolder.setDataSource(db.value());return jp.proceed();} finally {// 方法结束后清理当前数据源DataSourceHolder.clear();}
}

}

7.使用方法
@Mapper
public interface UserMapper {
@Select(“SELECT * FROM users”)
@Db(“ds1”)
List listUsersFromDs1();

@Select("SELECT * FROM users")
@Db("ds2")
List<User> listUsersFromDs2();

}


http://www.ppmy.cn/news/1014507.html

相关文章

一个月学通Python(三十三):Python并发编程在爬虫中的应用

专栏介绍 结合自身经验和内部资料总结的Python教程,每天3-5章,最短1个月就能全方位的完成Python的学习并进行实战开发,学完了定能成为大佬!加油吧!卷起来! 全部文章请访问专栏:《Python全栈教程(0基础)》 再推荐一下最近热更的:《大厂测试高频面试题详解》 该专栏对…

如何阅读webrtc的源代码呢?

了解代码库结构&#xff1a;首先&#xff0c;浏览整个代码库的目录结构&#xff0c;并了解每个目录和文件的作用。这将帮助你理解整个项目的组织方式和模块划分。 确定关注的模块&#xff1a;根据你的需求和兴趣&#xff0c;确定你想要深入研究的模块或功能。这可以是音视频处…

磁盘空间清理脚本

磁盘空间清理脚本&#xff0c;仅供参照 这是一个用于清理磁盘数据的 Shell 脚本&#xff0c;主要功能是根据设定的规则删除指定目录中的文件。以下是脚本的大致解释&#xff1a; cacheRoot/data&#xff1a;设置存储数据的根目录为 /data。 cleanDir$cacheRoot/record&#x…

laravel项目运行问题记录

一.首页404未找到 检查项目配置是否配置好 解决地址:phpstudy网站或站点创建成功,打开无响应_php打开提示站点创建成功_荒-漠的博客-CSDN博客 二.vendor目录不存在 composer未安装 解决地址:laravel安装composer依赖_荒-漠的博客-CSDN博客 三.首页可以展示 里面路径404 未配…

云专线的应用场景

云专线是连接用户本地数据中心和云上虚拟私有云的高安全、高速度、低延迟、稳定可靠的专属连接通道&#xff0c;主要有以下应用场景。 1、混合云环境&#xff1a;企业在私有云和公有云之间传输数据及部署应用时&#xff0c;使用云专线建立专用的网络连接&#xff0c;保证数据传…

CentOS 7 构建 LVS-DR 群集 nginx负载均衡

1、基于 CentOS 7 构建 LVS-DR 群集。 DS&#xff08;Director Server&#xff09;&#xff1a;DIP 192.168.231.132 & VIP 192.168.231.200 [root132 ~]# nmcli c show NAME UUID TYPE DEVICE ens33 c89f4a1a-d61b-4f24-a260…

C 语言的转义字符

转义字符也叫转移序列&#xff0c;包含如下&#xff1a; 转移序列 \0oo 和 \xhh 是 ASCII 码的特殊表示。 八进制数示例&#xff1a; 代码&#xff1a; #include<stdio.h> int main(void) {char beep\007;printf("%c\n",beep);return 0; }结果&#xff1a; …

openGauss学习笔记-33 openGauss 高级数据管理-视图

文章目录 openGauss学习笔记-33 openGauss 高级数据管理-视图33.1 语法格式33.2 参数说明33.3 示例 openGauss学习笔记-33 openGauss 高级数据管理-视图 视图与基本表不同&#xff0c;是一个虚拟的表。数据库中仅存放视图的定义&#xff0c;而不存放视图对应的数据&#xff0c…