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的配置信息。

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

相关推荐
月光水岸New17 分钟前
Ubuntu 中建的mysql数据库使用Navicat for MySQL连接不上
数据库·mysql·ubuntu
我爱松子鱼22 分钟前
mysql之规则优化器RBO
数据库·mysql
4277240025 分钟前
IDEA使用git不提示账号密码登录,而是输入token问题解决
java·git·intellij-idea
chengooooooo1 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
李长渊哦1 小时前
常用的 JVM 参数:配置与优化指南
java·jvm
计算机小白一个1 小时前
蓝桥杯 Java B 组之设计 LRU 缓存
java·算法·蓝桥杯
Tirzano1 小时前
springsecurity自定义认证
spring boot·spring
人间打气筒(Ada)2 小时前
MySQL主从架构
服务器·数据库·mysql
和道一文字yyds2 小时前
MySQL 中的索引数量是否越多越好?为什么?如何使用 MySQL 的 EXPLAIN 语句进行查询分析?MySQL 中如何进行 SQL 调优?
数据库·sql·mysql
南宫生4 小时前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode