SpringBoot+mybatis多数据源切换讲解

SpringBoot+mybatis多数据源切换讲解

1.背景:在工作中有多数据库源切换使用的场景,用别人写好的东西很方便,但是自己不知道原理用起来就是不放心
步骤一

引入所需的maven,版本选择自己适合的就好

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

自定义一个注解,用来实现在方法层面的数据库切换,一般来说为了代码的规范性,我们都会再写一个这种公共常量定义类

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
@Documented
public @interface TargetDataSource {
    String value() default DataSourceEnum.MasterDataSource;//你要选择的数据名称,建议写上默认值,你也不想每个涉及到数据库方法时都得加个注解吧
}
@Getter
public class DataSourceEnum {
   public static final String MasterDataSource = "first";
   public static final String SecondDataSource = "second";
}
步骤二

设置一个全局静态变量来保存我们的数据源配置

public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    public static void setDataSourceType(String dataSourceType) {
        contextHolder.set(dataSourceType);
    }
    public static String getDataSourceType() {
        return contextHolder.get();
    }
    public static void clearDataSourceType() {
        contextHolder.remove();
    }
}
步骤三

将具体的数据库信息从我们的配置文件中读取出来,如Nacos中或者本地的application.yml
通过@ConfigurationProperties,prefix中的信息就按照你的配置来,这里我们注入了两个数据库

@Configuration
public class DataSourceConfig {
    @Bean(name = DataSourceEnum.MasterDataSource)
    @ConfigurationProperties(prefix = "spring.datasource.first")
    public DataSource firstDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean(name = DataSourceEnum.SecondDataSource)
    @ConfigurationProperties(prefix = "spring.datasource.second")
    public DataSource secondDataSource() {
        return DataSourceBuilder.create().build();
    }
    // 动态数据源
    @Primary
    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource(@Qualifier(DataSourceEnum.MasterDataSource) DataSource defaultDataSource,
                                        @Qualifier(DataSourceEnum.SecondDataSource) DataSource secondaryDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceEnum.MasterDataSource, defaultDataSource);
        targetDataSources.put(DataSourceEnum.SecondDataSource, secondaryDataSource);

        AbstractRoutingDataSource dynamicDataSource = new AbstractRoutingDataSource() {
            @Override
            protected Object determineCurrentLookupKey() {
                return DataSourceContextHolder.getDataSourceType();
            }
        };
        dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }
}
步骤四

通过切面AOP技术,将我们定义的注解拦截下来,每当Sping检查到我们的注解时,去读取我们在前面全局变量保存的信息,去做数据源切换。
通过@Before,在方法执行前去切换,注意要有@After去把这一次数据库连接完后去删除掉你切换的数据源,不然会影响其他方法。

@Aspect
@Component
public class DataSourceAspect {
    @Before("@annotation(targetDataSource)")
    public void beforeSwitchDataSource(JoinPoint joinPoint, TargetDataSource targetDataSource) {
        String dataSourceName = targetDataSource.value();
        DataSourceContextHolder.setDataSourceType(dataSourceName);
    }

    @After("@annotation(targetDataSource)")
    public void afterSwitchDataSource(JoinPoint joinPoint, TargetDataSource targetDataSource) {
        DataSourceContextHolder.clearDataSourceType();
    }
}
步骤五

将我们定义的dynamicDataSource通过sqlSessionFactory注入mybatis,使其生效。Mybaits在SpringBoot启动时会去查找类型为DataSource的Bean,这就是为什么那里要加一个@Primary。DataSource必须先Mybaits一步注入进去,不然就错过了。

@Configuration
@MapperScan(basePackages = "com.lordyi.mapper",sqlSessionFactoryRef = "sqlSessionFactory")
public class MybatisConfig {
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactory=new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dynamicDataSource);
        return sqlSessionFactory.getObject();
    }
}
步骤六

把自己的数据库配置写好

spring:
  datasource:
    first:
      jdbc-url: jdbc:mysql://****:3306/***?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
      username: **
      password: **
      driver-class-name: com.mysql.cj.jdbc.Driver
    second:
      jdbc-url: jdbc:mysql://****:3306/***?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
      username: **
      password: **
      driver-class-name: com.mysql.cj.jdbc.Driver

到这一步你就可以愉快的拿着@TargetDataSource(“youDataBase”)玩耍了,觉得对您有帮助的请点一个免费的赞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值