SpringBoot多数据源

  3 分钟   11279 字    |    

SpringBoot多数据源

1 手动切换数据源

  1. application.properties
# 主数据库:TDengine
# 数据源驱动
spring.datasource.primary.driver-class-name=com.taosdata.jdbc.rs.RestfulDriver
# 数据库连接地址
# 多数据源写jdbc-url
spring.datasource.primary.jdbc-url=jdbc:TAOS-RS://localhost:6041/workshop?timezone=UTC+8&charset=UTF-8&locale=en_US.UTF-8
# 数据库用户名&密码
spring.datasource.primary.username=root
spring.datasource.primary.password=
# 副数据库:MySQL
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据库连接地址
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/augment?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false
# 数据库用户名&密码
spring.datasource.secondary.username=root
spring.datasource.secondary.password=
  1. 主数据源配置

PrimaryDataSourceConfig.java

@Configuration
// 指定主数据库扫描对应的Mapper文件夹,生成代理对象
@MapperScan(basePackages ="com.dec.workshop.iot.mapper" ,sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {
    /**
     * 主数据源,Primary注解必须增加,它表示该数据源为默认数据源
     * 项目中还可能存在其他的数据源,如获取时不指定名称,则默认获取这个数据源,如果不添加,则启动时候回报错
     */
    @Primary
    @Bean(name = "primaryDataSource")
    // 读取spring.datasource.primary前缀的配置文件映射成对应的配置对象
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource dataSource() {
        DataSource build = DataSourceBuilder.create().build();
        return build;
    }

    /**
     * 事务管理器,Primary注解作用同上
     */
    @Bean(name = "primaryTransactionManager")
    @Primary
    public PlatformTransactionManager dataSourceTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * session工厂,Primary注解作用同上
     */

    @Bean(name = "primarySqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        //sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(primaryDataSourceConfig.MAPPER_LOCATION));
        return sessionFactoryBean.getObject();
    }
}
  1. 次数据源配置

SecondaryDataSourceConfig.java

@Configuration
@MapperScan(basePackages ="com.dec.workshop.manager.mapper" ,sqlSessionFactoryRef = "secondarySqlSessionFactory")
public class SecondaryDataSourceConfig {

    @Bean(name = "secondaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource dataSource() {
        DataSource build = DataSourceBuilder.create().build();
        return build;
    }

    @Bean(name = "secondaryTransactionManager")
    public PlatformTransactionManager dataSourceTransactionManager(@Qualifier("secondaryDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "secondarySqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("secondaryDataSource") DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        return sessionFactoryBean.getObject();
    }
}
  1. 对某数据库进行操作时,调用对应的mapper即可

2 动态切换数据源

  1. 配置文件

application.properties

# 主数据库:TDengine
# 数据源驱动
spring.datasource.primary.driver-class-name=com.taosdata.jdbc.rs.RestfulDriver
# 数据库连接地址
spring.datasource.primary.jdbc-url=jdbc:TAOS-RS://localhost:6041/workshop?timezone=UTC+8&charset=UTF-8&locale=en_US.UTF-8
# 数据库用户名&密码
spring.datasource.primary.username=root
spring.datasource.primary.password=taosdata
# 副数据库:MySQL
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据库连接地址
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/augment?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false
# 是否启用从数据库
spring.datasource.secondary.enabled=true
# 数据库用户名&密码
spring.datasource.secondary.username=root
spring.datasource.secondary.password=qwe123qwe
  1. 数据源配置

DataSourceConfig.java

@Configuration
public class DataSourceConfig {
    /**
     * db1数据库配置
     */
    @Bean("primary")
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primarySource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * db2数据库配置
     */
    @Bean("secondary")
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    @ConditionalOnProperty(prefix = "spring.datasource.secondary", name = "enabled", havingValue = "true")
    public DataSource secondarySource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 动态数据库配置
     */
    @Primary
    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 默认数据源
        dynamicDataSource.setDefaultTargetDataSource(primarySource());

        // 配置多数据源
        Map<Object, Object> dsMap = new HashMap(5);
        dsMap.put("primary", primarySource());
        dsMap.put("secondary", secondarySource());

        dynamicDataSource.setTargetDataSources(dsMap);

        return dynamicDataSource;
    }

    /**
     * 配置@Transactional注解事物
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }
}

DataSourceContextHolder.java

public class DataSourceContextHolder {
    // 默认数据源
    public static final String DEFAULT_DS = "primary";

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDB(String dbType) {
        contextHolder.set(dbType);
    }

    public static String getDB() {
        return (contextHolder.get());
    }

    public static void clearDB() {
        contextHolder.remove();
    }
}

DynamicDataSource.java

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDB();
    }
}
  1. 注解

DataBase.java

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DataBase {
    String value() default "primary";
}
  1. 切面

DataBaseAspect.java

@Aspect
@Component
public class DataBaseAspect {

    @Pointcut("@annotation(com.dec.core.annotation.DataBase)")
    public void dbPointCut() {

    }

    @Before("dbPointCut()")
    public void beforeSwitchDS(JoinPoint point){
        //获得当前访问的class
        Class<?> className = point.getTarget().getClass();
        //获得访问的方法名
        String methodName = point.getSignature().getName();
        //得到方法的参数的类型
        Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();

        String dataSource = DataSourceContextHolder.DEFAULT_DS;
        try {
            // 得到访问的方法对象
            Method method = className.getMethod(methodName, argClass);

            // 判断是否存在@DateBase注解
            if (method.isAnnotationPresent(DataBase.class)) {
                DataBase annotation = method.getAnnotation(DataBase.class);
                // 取出注解中的数据源名
                dataSource = annotation.value();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 切换数据源
        DataSourceContextHolder.setDB(dataSource);
    }

    @After("dbPointCut()")
    public void afterSwitchDS(JoinPoint point){
        DataSourceContextHolder.clearDB();
    }
}
  1. 使用
@DataBase("primary")
    public void test(){
      return;
    }

Service方法中直接调用注解

3 调用已有轮子

  1. pom.xml
<!--导入MyBatis-Plus作为持久层框架-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>
<!--动态数据源-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.4.0</version>
</dependency>
  1. application.yaml
spring:
  datasource:
    dynamic:
      primary: primary #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        primary:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/workshop?serverTimezone
          username: root
          password: qwe123qwe
        secondary:
          driver-class-name: com.taosdata.jdbc.rs.RestfulDriver
          url: jdbc:TAOS-RS://localhost:6041/workshop?timezone
          username: root
          password: taosdata
  1. 使用

方法上:@DS("secondary")

参考

  1. https://juejin.cn/post/7025511138364227621
  2. https://www.jianshu.com/p/1912d2599473
  3. https://www.baomidou.com/pages/a61e1b/#dynamic-datasource
~  ~  The   End  ~  ~


 赏 
感谢您的支持,我会继续努力哒!
支付宝收款码
tips
文章二维码 分类标签:,none
文章标题:SpringBoot多数据源
文章链接:http://120.46.217.131:82/archives/63/
最后编辑:2023 年 5 月 29 日 22:00 By Yang
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)

相关推荐

热门推荐

(*) 5 + 4 =
快来做第一个评论的人吧~