在Spring Boot中,当我们需要使用多数据源的时候,通常会面临一些挑战,比如如何动态切换数据源以及如何管理多个数据源的配置。为了解决这些问题,我们可以使用@DS注解和自定义的DynamicDataSource实现。这两种方式各有优缺点,适用于不同的场景。

一、@DS 注解的使用

@DS注解是使用mybatis-plus框架提供的,通常适合具有明确数据源标识的情况。通过这种方式,可以很方便地在服务层或者DAO层标识当前使用的数据源。

首先,在pom.xml中添加mybatis-plus依赖:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3</version>
</dependency>

接下来,定义数据源的属性,比如在application.yml中:

spring:
  datasource:
    ds1:
      url: jdbc:mysql://localhost:3306/test1
      username: root
      password: password
    ds2:
      url: jdbc:mysql://localhost:3306/test2
      username: root
      password: password

然后,我们创建一个服务,使用@DS注解选择数据源:

import com.baomidou.dynamic.datasource.annotation.DS;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @DS("ds1") // 使用第一个数据源
    public void methodUsingDs1() {
        // 调用 ds1 数据源的相关操作
    }

    @DS("ds2") // 使用第二个数据源
    public void methodUsingDs2() {
        // 调用 ds2 数据源的相关操作
    }
}

通过这种方式,@DS 注解可以在方法级别上灵活切换数据源,非常适合某些方法需要显式指定数据源的场合。

二、DynamicDataSource自定义实现

当需要更灵活地管理多数据源时,可以选择自定义DynamicDataSource。此实现适合于需要在运行时根据某些条件动态选择数据源的场景。

首先,我们定义一个数据源配置类,使用AbstractRoutingDataSource来实现动态选择数据源:

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceType(); // 获取当前线程绑定的数据源类型
    }
}

接着,创建一个DataSourceContextHolder用于存储和获取当前数据源类型:

public class DataSourceContextHolder {
    private static final ThreadLocal<String> CONTEXT = new ThreadLocal<>();

    public static void setDataSourceType(String dataSourceType) {
        CONTEXT.set(dataSourceType);
    }

    public static String getDataSourceType() {
        return CONTEXT.get();
    }

    public static void clearDataSourceType() {
        CONTEXT.remove();
    }
}

接下来,在配置类中配置数据源:

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.ds1")
    public DataSource ds1() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.ds2")
    public DataSource ds2() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public DynamicDataSource dataSource(@Qualifier("ds1") DataSource ds1,
                                         @Qualifier("ds2") DataSource ds2) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("ds1", ds1);
        targetDataSources.put("ds2", ds2);

        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(ds1); // 设置默认数据源
        return dynamicDataSource;
    }
}

在使用时,我们可以通过DataSourceContextHolder来设置当前操作使用的数据源:

public void someServiceMethod() {
    try {
        DataSourceContextHolder.setDataSourceType("ds1");
        // 进行操作
    } finally {
        DataSourceContextHolder.clearDataSourceType(); // 清除当前数据源类型
    }
}

总结

这两种方式各有利弊:

  1. 使用@DS注解更加简单,适用于明确需要使用不同数据源的场景。
  2. 自定义DynamicDataSource提供更大的灵活性,适用于需要程序逻辑决定数据源的复杂场景。

根据实际需求,可以选择合适的方式来实现多数据源的管理。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部