【问题标题】:Using two datasources in Spring Boot在 Spring Boot 中使用两个数据源
【发布时间】:2017-03-30 23:54:35
【问题描述】:

我在我的项目中使用Spring Boot 1.3.3 一个数据库,现在我想使用两个具有相同架构不同连接的数据库强>。

我想使用相同的存储库、实体并找到方法告诉 spring 我想根据情况使用哪个数据源。

【问题讨论】:

  • 在 application.yml 中使用 Spring 活动配置文件
  • @Zubair 我想同时使用两者,并根据我的服务情况选择一个或另一个。
  • @JeanCedron 这是一个复杂的设置。不要回避这个问题,但您是否考虑过使用消息传递层来促进这一点? Decider App 决定要持久化到哪个数据源。然后它将消息发送到特定于数据源的队列,工作节点为其读取并保存数据。只是一个想法......我已经完成了一些双数据源应用程序,但它们在实体、存储库等方面完全分开。

标签: java spring spring-boot spring-data datasource


【解决方案1】:

如果有人遇到这个问题,我已经找到了解决方案:

首先,您的 application.properties 应如下所示:

datasource:
primary:
    url: jdbc:mysql://localhost:3306/primary_db
    username: your_username
    password: your_password
    driver-class-name: com.mysql.jdbc.Driver
secondary:
    url: jdbc:mysql://localhost:3306/secondary_db
    username: your_username
    password: your_password
    driver-class-name: com.mysql.jdbc.Driver

之后,您必须使用您的数据库创建一个枚举:

public enum Database {
    PRIMARY,
    SECONDARY
}

然后,你创建一个 ThreadLocal:

public class DatabaseThreadContext {

    private static final ThreadLocal<Database> current = new ThreadLocal<>();

    public static void setCurrentDatabase(Database database) {
        current.set(database);
    }

    public static Object getCurrentDatabase() {
        return current.get();
    }

}

魔法来了,您必须使用 AbstractRoutingDataSource,它早在 2007 年的 Spring 2 中就已实现:

public class RoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DatabaseThreadContext.getCurrentDatabase();
    }

}

最后在你的 Spring Boot 应用中注入一个配置:

@Configuration
public class DatabaseRouter {

    @Bean
    @ConfigurationProperties(prefix="datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

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

    @Bean
    @Primary
    public DataSource dataSource() {
        Map<Object, Object> targetDatasources = new HashMap<Object, Object>(){{
            put(Database.SECONDARY, secondaryDataSource());
            put(Database.PRIMARY, primaryDataSource());
        }};
        RoutingDataSource routingDataSource = new RoutingDataSource();
        routingDataSource.setDefaultTargetDataSource(primaryDataSource());
        routingDataSource.setTargetDataSources(targetDatasources);
        routingDataSource.afterPropertiesSet();
        return routingDataSource;
    }

}

在每个请求中,如果您想在数据库之间进行更改,您只需使用此功能:DatabaseThreadContext.setCurrentDatabase(Database.PRIMARY);

此外,您可以同时拥有两个以上的数据库。

【讨论】:

    猜你喜欢
    • 2021-06-22
    • 2020-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 2019-12-10
    相关资源
    最近更新 更多