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

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

相关推荐
twj_one几秒前
java中23种设计模式
java·开发语言·设计模式
怣5012 分钟前
MySQL表筛选分组全解析:排序、分组与限制的艺术
数据库·mysql
tsyjjOvO16 分钟前
JDBC(Java Database Connectivity)
java·数据库
qq_124987075320 分钟前
基于springboot的尿毒症健康管理系统的设计与实现(源码+论文+部署+安装)
java·spring boot·spring·毕业设计·计算机毕业设计
编程彩机23 分钟前
互联网大厂Java面试:从Spring Boot到微服务优化场景解析
spring boot·分布式事务·微服务架构·java面试·技术解析
猿小羽1 小时前
Flyway + Spring Boot:实现数据库迁移的最佳实践
spring boot·编程·flyway·最佳实践·数据库迁移
黎子越1 小时前
python相关练习
java·前端·python
电商API&Tina1 小时前
电商数据采集 API 接口 全维度解析(技术 + 商业 + 合规)
java·大数据·开发语言·数据库·人工智能·json
liwulin05061 小时前
【JSON】使用com.fasterxml.jackson解析json字符串
java·数据库·json
ActionTech1 小时前
MySQL 用好 Optimizer Trace,深刻理解 SQL 优化过程!
sql·mysql·oracle