SpringBoot中使用AbstractRoutingDataSource

本文目的是为了让你快速在Springboot中使用多数据库切换,并非研究类型文章~

本文说的方法也是使用AbstractRoutingDataSource,因此和SpringMVC中使用需要的类完全一样,仅仅是配置略有不同。阅读本文之前请先参考
https://blog.csdn.net/lizhengwei1989/article/details/88081703
了解使用过程中自定义的类

下面假设自定义的类已经有了,接下来的配置如下:

使用到了另一篇文章中一样的类有:

DataSourceContextHolder
DataSourceKey
DynamicDataSource
DynamicDataSourceAspect
TargetDataSource

你可以直接拷贝使用

不一样的改动有
首先,你的启动类上的配置

//指定aop事务执行顺序,已保证在切换数据源的后面
@EnableTransactionManagement(order = 2)
//排除数据源自动配置
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class ToolApplication {

	public static void main(String[] args) {
		SpringApplication.run(ToolApplication.class, args);
	}

}

其次,新增了一个类,这个类和前面提到的5个类放一起就好了

package com.ifeng.tool.dynamic;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

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

@Configuration
public class DynamicDataSourceConfiguration {

    @Primary
    @Bean(name = "clickhouseDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.clickhouse")
    public DataSource masterDataSource() {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        dataSource.setName("clickhouseDataSource");
        return dataSource;
    }

    @Bean(name = "brandDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.brand")
    public DataSource slaveDataSource() {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        dataSource.setName("brandDataSource");
        return dataSource;
    }

    /**
     * 动态数据源: 通过AOP在不同数据源之间动态切换
     * @return
     */
    @Bean(name = "dynamicDataSource")
    public DataSource dataSource(@Autowired @Qualifier("clickhouseDataSource") DataSource primery,@Autowired @Qualifier("brandDataSource") DataSource brand) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 默认数据源
        dynamicDataSource.setDefaultTargetDataSource(primery);

        // 配置多数据源
        Map<Object, Object> dsMap = new HashMap<Object, Object>();
        dsMap.put("clickhouse", primery);
        dsMap.put("brand", brand);
        dynamicDataSource.setTargetDataSources(dsMap);
        return dynamicDataSource;
    }

    @Bean
    public PlatformTransactionManager txManager(DataSource dynamicDataSource) {
        return new DataSourceTransactionManager(dynamicDataSource);
    }

    @Bean("sqlSessionFactory")
    @ConfigurationProperties(prefix = "mybatis")
    public SqlSessionFactoryBean sqlSessionFactoryBean(@Autowired @Qualifier("dynamicDataSource") DataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);
        return sqlSessionFactoryBean;
    }

    @Bean
    @ConfigurationProperties(prefix = "mybatis")
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("com.testxxxx.tool");
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        return mapperScannerConfigurer;
    }

}

对应的数据库配置是

spring.datasource.clickhouse.driver-class-name:ru.yandex.clickhouse.ClickHouseDriver
spring.datasource.clickhouse.url:jdbc:clickhouse://xxxxxxxx/ods
spring.datasource.clickhouse.username:
spring.datasource.clickhouse.password:

spring.datasource.brand.driver-class-name:com.mysql.jdbc.Driver
spring.datasource.brand.url:jdbc:mysql://xxxxxxx/ibs
spring.datasource.brand.username:xxxxx
spring.datasource.brand.password:xxxxxxx

配置就够了,实测切换没有问题

以下是SpringBoot整合MyBatisPlus配置信息的步骤: 1.在pom.xml文件添加MyBatisPlus和MySQL驱动的依赖: ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> ``` 2.在application.yml文件配置数据源信息和MyBatisPlus的相关配置: ```yaml spring: datasource: dynamic: primary: master datasource: master: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/db_master?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: root slave: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/db_slave?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: root mybatis-plus: mapper-locations: classpath*:mapper/**/*.xml type-aliases-package: com.example.demo.entity ``` 3.创建数据源配置类DynamicDataSourceConfig,用于动态切换数据源: ```java @Configuration public class DynamicDataSourceConfig { @Bean @ConfigurationProperties("spring.datasource.druid.master") public DataSource masterDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean @ConfigurationProperties("spring.datasource.druid.slave") public DataSource slaveDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean @Primary public DynamicDataSource dataSource(DataSource masterDataSource, DataSource slaveDataSource) { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put(DataSourceEnum.MASTER.getName(), masterDataSource); targetDataSources.put(DataSourceEnum.SLAVE.getName(), slaveDataSource); return new DynamicDataSource(masterDataSource, targetDataSources); } } ``` 4.创建数据源枚举类DataSourceEnum,用于定义数据源的名称: ```java public enum DataSourceEnum { MASTER("master"), SLAVE("slave"); private String name; DataSourceEnum(String name) { this.name = name; } public String getName() { return name; } } ``` 5.创建动态数据源类DynamicDataSource,用于动态切换数据源: ```java public class DynamicDataSource extends AbstractRoutingDataSource { private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>(); private final Map<Object, Object> targetDataSources; public DynamicDataSource(DataSource defaultDataSource, Map<Object, Object> targetDataSources) { super.setDefaultTargetDataSource(defaultDataSource); this.targetDataSources = targetDataSources; super.setTargetDataSources(this.targetDataSources); super.afterPropertiesSet(); } @Override protected Object determineCurrentLookupKey() { return getDataSource(); } 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(); } @Override public void afterPropertiesSet() { super.afterPropertiesSet(); } } ``` 6.创建数据源切换的AOP类DataSourceAspect,用于在方法执行前切换数据源: ```java @Aspect @Component public class DataSourceAspect { @Pointcut("@annotation(com.example.demo.annotation.DataSource)") public void dataSourcePointCut() { } @Before("dataSourcePointCut()") public void before(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); DataSource dataSource = signature.getMethod().getAnnotation(DataSource.class); if (dataSource == null) { DynamicDataSource.setDataSource(DataSourceEnum.MASTER.getName()); } else { DynamicDataSource.setDataSource(dataSource.value().getName()); } } @After("dataSourcePointCut()") public void after(JoinPoint joinPoint) { DynamicDataSource.clearDataSource(); } } ``` 7.在Mapper接口使用@Mapper注解,并在Mapper.xml文件使用MyBatisPlus提供的标签进行SQL语句的编写。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值