Spring Boot项目MySQL数据源切换

由于在主库发现的我的一条SQL的慢查询、之前都是直接连一个数据库、后面让他改成查询的SQL连另一台从库。

于是我第一时间打开了大家的百度、后续总结复制粘贴了一个完整的案例并线上使用了、环境版本不一样可能使用的配置不一样、所以仅供参考。

Spring Boot、Druid、Mybatis、MySQL

xml 复制代码
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.3.RELEASE</version>
</parent>
<!-- Mybatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.2</version>
</dependency>
<!-- mysql 数据库驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.25</version>
</dependency>
<!-- druid 数据库连接池 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.17</version>
</dependency>
yaml 复制代码
spring:
  datasource:
    master:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: 123456
    slave:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: 123456
      # druid 连接池配置接着往下配置就OK
      max-active: 12
java 复制代码
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {
    public static final String MASTER = "MASTER"; // 写
    public static final String SLAVE = "SLAVE"; // 读
    private static final ThreadLocal<String> DYNAMIC_DATASOURCE_KEY = new ThreadLocal<>();
    public static String getDynamicDataSourceKey() {
        String val = DYNAMIC_DATASOURCE_KEY.get();
        return val == null ? DynamicDataSource.MASTER : val;
    }
    public static void setDynamicDataSourceKey(String key) {
        DYNAMIC_DATASOURCE_KEY.set(key);
    }
    public static void removeDynamicDataSourceKey() {
        DYNAMIC_DATASOURCE_KEY.remove();
    }
    @Override
    protected Object determineCurrentLookupKey() {
        String dynamicDataSourceKey = getDynamicDataSourceKey();
        log.info("当前数据源:[{}]", dynamicDataSourceKey);
        return dynamicDataSourceKey;
    }
}
java 复制代码
@Configuration
public class DataSourceConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DruidDataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        return DruidDataSourceBuilder.create().build();
    }
    @Bean("dynamicDataSource")
    public DynamicDataSource dynamicDataSource() {
        DynamicDataSource dynamicRoutingDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>(2);
        targetDataSources.put(DynamicDataSource.MASTER, masterDataSource());
        targetDataSources.put(DynamicDataSource.SLAVE, slaveDataSource());

        dynamicRoutingDataSource.setDefaultTargetDataSource(slaveDataSource());
        dynamicRoutingDataSource.setTargetDataSources(targetDataSources);
        dynamicRoutingDataSource.afterPropertiesSet();
        return dynamicRoutingDataSource;
    }
    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource datasource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(datasource);
        // 映射文件地址
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        // 所有Entity别名类所在包
        bean.setTypeAliasesPackage("com.suka.entity");
        return bean.getObject();
    }
}
java 复制代码
@Slf4j
@Aspect
@Order(1)
@Component
public class DataSourceAspect {
    @Pointcut("execution(* com.suka.mapper.*.*(..))")
    public void dsPointCut() {
    }
    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        String methodName = signature.getMethod().getName();
        // get/sel/select/find 开的头的Mapper类中的方法就切换。
        if (methodName.startsWith("get") || methodName.startsWith("sel")
                || methodName.startsWith("select") || methodName.startsWith("find")) {
            DynamicDataSource.setDynamicDataSourceKey(DynamicDataSource.SLAVE);
        }
        try {
            return point.proceed();
        } finally {
            DynamicDataSource.removeDynamicDataSourceKey();
        }
    }
}

两个注意点:DataSourceAspect类是需要引入AOP依赖、sqlSessionFactory是Mybatis需要的、里面可以配置一些扫描包的配置以及类别名之类相关Mybatis的配置信息。

问题来了、如何校验我这个查询方法或者插入方法是走的那个配置的数据源呢、你去把配置文件中的数据库写一个错的不就可以校验了、如果报错了就证明是用的这个配置的数据源!!!

相关推荐
悄悄地努力5 分钟前
IDEA 新建 SpringBoot 项目时,没有高版本 SpringBoot 可选
java·spring boot·intellij-idea
救救孩子把1 小时前
Mac 环境下 JDK 版本切换全指南
java·开发语言·macos
路飞雪吖~1 小时前
【Linux】共享内存
java·linux·服务器
caihuayuan41 小时前
鸿蒙AI开发:10-多模态大模型与原子化服务的集成
java·大数据·sql·spring·课程设计
张哈大1 小时前
【 Redis | 实战篇 秒杀优化 】
java·数据库·redis·笔记·缓存
Musennn1 小时前
MySQL多条件查询深度解析
大数据·数据库·mysql
低维歌者1 小时前
python训练营day27
java·开发语言·python
大帅不是我2 小时前
Python多进程编程执行任务
java·前端·python
purrrew3 小时前
【Java ee初阶】jvm(3)
java·jvm
Hello World......4 小时前
Java求职面试揭秘:从Spring到微服务的技术挑战
大数据·hadoop·spring boot·微服务·spark·java面试·互联网大厂