Spring Boot多个数据源-连接错误处理

时间:2019-05-06 13:08:41

标签: spring-boot exception spring-data-jpa database-connection datasource

我正在Spring Boot Rest应用程序中使用多个数据源(Oracle和SQL-Server)。在此应用程序中,我有超过25个以上的端点可以处理客户端请求。但是,当由于某种原因像Oracle或SQL-server这样的一个数据库关闭时,我的应用程序无法启动服务器。

在Google和堆栈溢出中看到了几个示例,但它们与我正在寻找的示例不同...

package com.foobar;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories
(
  entityManagerFactoryRef = "entityManagerFactory",
  basePackages = { "com.foobar.foo.repo" }
)
public class FooDbConfig 
{
  @Primary
  @Bean(name = "dataSource")
  @ConfigurationProperties(prefix = "spring.datasource")
  public DataSource dataSource() {
    return DataSourceBuilder.create().build();
  }

  @Primary
  @Bean(name = "entityManagerFactory")
  public LocalContainerEntityManagerFactoryBean 
  entityManagerFactory(
    EntityManagerFactoryBuilder builder,
    @Qualifier("dataSource") DataSource dataSource
  ) {
    return builder
      .dataSource(dataSource)
      .packages("com.foobar.foo.domain")
      .persistenceUnit("foo")
      .build();
  }

  @Primary
  @Bean(name = "transactionManager")
  public PlatformTransactionManager transactionManager(
    @Qualifier("entityManagerFactory") EntityManagerFactory 
    entityManagerFactory)
 {
    return new JpaTransactionManager(entityManagerFactory);
  }
}

第二个数据源的配置相同,但属性不同。

我正在使用以下示例作为实现我的要求的基本代码参考
Example link

我正在寻找一种解决方案,如果N个应用程序中有一个数据库服务器应该启动并处理客户端请求,并且只要有第二个数据库服务器可用,它就会自动连接并处理其他端点请求

1 个答案:

答案 0 :(得分:-1)

我最近为使用数据源和使用liquibase的多租户创建了一个解决方案,但如果不使用liquibase,也可以删除它!

application.yml示例

spring:
  dataSources:
    - tenantId: db1
      url: jdbc:postgresql://localhost:5432/db1
      username: postgres
      password: 123456
      driver-class-name: org.postgresql.Driver
      liquibase:
        enabled: true
        default-schema: public
        change-log: classpath:db/master/changelog/db.changelog-master.yaml
    - tenantId: db2
      url: jdbc:postgresql://localhost:5432/db2
      username: postgres
      password: 123456
      driver-class-name: org.postgresql.Driver
    - tenantId: db3
      url: jdbc:postgresql://localhost:5432/db3
      username: postgres
      password: 123456
      driver-class-name: org.postgresql.Driver

DataSourceConfiguration

@Configuration
@EnableTransactionManagement
@EntityScan(basePackages = { "br.com.dijalmasilva.springbootmultitenancyliquibase" })
@EnableJpaRepositories(basePackages = { "br.com.dijalmasilva.springbootmultitenancyliquibase" })
public class DataSourceConfiguration {

    @Bean(name = "dataSources")
    @Primary
    public Map<Object, Object> getDataSources(DataSourceProperties dataSourceProperties) {
        return dataSourceProperties.getDataSources().stream().map(dataSourceProperty -> {
            DataSource dataSource = DataSourceBuilder.create()
                    .url(dataSourceProperty.getUrl())
                    .username(dataSourceProperty.getUsername())
                    .password(dataSourceProperty.getPassword())
                    .driverClassName(dataSourceProperty.getDriverClassName())
                    .build();
            return new TenantIdDataSource(dataSourceProperty.getTenantId(), dataSource);
        }).collect(Collectors.toMap(TenantIdDataSource::getTenantId, TenantIdDataSource::getDataSource));
    }

    @Bean(name = "tenantRoutingDataSource")
    @DependsOn("dataSources")
    public DataSource dataSource(Map<Object, Object> dataSources) {
        AbstractRoutingDataSource tenantRoutingDataSource = new TenantRoutingDataSource();
        tenantRoutingDataSource.setTargetDataSources(dataSources);
        tenantRoutingDataSource.setDefaultTargetDataSource(dataSources.get("db1"));
        tenantRoutingDataSource.afterPropertiesSet();
        return tenantRoutingDataSource;
    }

    @Data
    @AllArgsConstructor
    private class TenantIdDataSource {
        private Object tenantId;
        private Object dataSource;
    }
}

TenantRoutingDataSource

public class TenantRoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return TenantContext.getCurrentTenant();
    }
}

DataSourceProperties

@Data
@Component
@ConfigurationProperties(prefix = "spring")
public class DataSourceProperties {

    private List<DataSourceProperty> dataSources = new ArrayList<>();
}

DataSourceProperty

@Data
public class DataSourceProperty {

    private String tenantId;
    private String url;
    private String username;
    private String password;
    private String driverClassName;
    private LiquibaseProperties liquibase;
}

查看完整的代码,也许可以帮助您!

项目链接:https://github.com/dijalmasilva/spring-boot-multitenancy-datasource-liquibase