SpringBoot-使用AbstractRoutingDataSource进行多数据源管理


数据源配置 - DruidDataSource

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    w1:
      url: jdbc:postgresql://localhost:55432/study
      username: user
      password: pw
    r1:
      url: jdbc:postgresql://localhost:55433/study
      username: user
      password: pw
@Configuration
public class DBConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.w1")
    public DataSource dsw1() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.r1")
    public DataSource dsr1() {
        return DruidDataSourceBuilder.create().build();
    }

}

多数据源配置 - AbstractRoutingDataSource

@Component
@Primary
@RequiredArgsConstructor
public class DynamicDataSource extends AbstractRoutingDataSource {
    // 当前使用的数据源标识
    public static ThreadLocal<DSType> name=new ThreadLocal<>();
    private final DataSource dsr1;
    private final DataSource dsw1;

    // 返回当前数据源标识
    @Override
    protected Object determineCurrentLookupKey() {
        return name.get();
    }

    @Override
    public void afterPropertiesSet() {
        // 为targetDataSources初始化所有数据源
        Map<Object, Object> targetDataSources=new HashMap<>();
        targetDataSources.put(DSType.W1,dsw1);
        targetDataSources.put(DSType.R1,dsr1);
        super.setTargetDataSources(targetDataSources);
        // 为defaultTargetDataSource 设置默认的数据源
        super.setDefaultTargetDataSource(dsw1);
        super.afterPropertiesSet();
    }

}

多数据源自动切换 - AOP

public enum DSType {
    R1,
    W1,
}
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface DDS {
    DSType value() default DSType.W1;
}
@Component
@Aspect
@Order(0)
public class DynamicDataSourceAspect {

    @Before(value = "@annotation(dds)", argNames = "point,dds")
    public void before(JoinPoint point, @NonNull DDS dds) {
        DSType type = dds.value();
        DynamicDataSource.name.set(type);
    }

}

Dao & Mapper - Mybatis

@Data
@Accessors(chain = true)
@TableName("r")
public class R {
    @TableId
    private Integer id;
    private String name;
}

@Data
@Accessors(chain = true)
@TableName("w")
public class W {
    @TableId
    private Integer id;
    private String name;
}
@Mapper
public interface RMapper {
    @Select("select * from r")
    List<R> selectAll();
}

@Mapper
public interface WMapper {
    @Select("select * from w")
    List<W> selectAll();
}

切换数据源 - @DDS(DSType.W1)

public interface SelectService {
    String selectWAll();
    String selectRAll();
}

@Service
@RequiredArgsConstructor
public class SelectServiceImpl implements SelectService {
    private final RMapper rMapper;
    private final WMapper wMapper;

    @DDS(DSType.W1)
    @Override
    public String selectWAll() {
        return JSON.toJSONString(wMapper.selectAll());
    }

    @DDS(DSType.R1)
    @Override
    public String selectRAll() {
        return JSON.toJSONString(rMapper.selectAll());
    }

}

测试 - SpringBootTest

@Slf4j
@SpringBootTest
class SelectServiceImplTest {
    @Autowired
    private SelectService selectService;

    @Test
    void selectWAll() {
        log.info(selectService.selectWAll());
    }

    @Test
    void selectRAll() {
        log.info(selectService.selectRAll());
    }

}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.jxch.study</groupId>
    <artifactId>study-springcloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>study-springcloud</name>
    <description>study-springcloud</description>
    <properties>
        <java.version>20</java.version>
        <spring-cloud.version>2022.0.2</spring-cloud.version>
        <spring-boot.version>3.0.6</spring-boot.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.14.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.18</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.28</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.2.23</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>2.0.33</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${spring-boot.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

库表结构 - sql

create table public.w (
  id integer primary key not null,
  name character varying(100)
);

create table public.r (
  id integer primary key not null,
  name character varying(100)
);

数据库部署 - docker-compose

version: '3.8'
services:
  db_w1:
    image: postgres
    restart: unless-stopped
    ports:
      - "55432:5432"
    volumes:
      - ./data/db_w1:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=pw
      - POSTGRES_USER=user
      - POSTGRES_DB=study
  db_r1:
    image: postgres
    restart: unless-stopped
    ports:
      - "55433:5432"
    volumes:
      - ./data/db_r1:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=pw
      - POSTGRES_USER=user
      - POSTGRES_DB=study

文章作者: 钱不寒
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 钱不寒 !
  目录