Spring boot несколько источников данных - обработка ошибок подключения - PullRequest
0 голосов
/ 06 мая 2019

Я работаю с несколькими источниками данных (Oracle и SQL-Server) в приложении Spring Boot Rest.В этом приложении у меня есть более 25+ конечных точек для обработки клиентских запросов.Но когда одна из баз данных недоступна, например, Oracle или SQL-сервер по какой-то причине недоступны, мое приложение не может запустить сервер.

Посмотрел пару примеров по 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);
  }
}

та же конфигурация для 2-го источника данных, но с разными свойствами.

Я использую приведенный ниже пример в качестве ссылки на базовый код для реализации моих требований
Пример ссылки

Я ищу решение, если один сервер БДприложение, доступное из N, должно запускать и обрабатывать клиентские запросы, а когда доступен второй сервер БД, оно автоматически подключается и обрабатывает запросы других конечных точек

1 Ответ

0 голосов
/ 12 мая 2019

Недавно я создал решение для мультитенанса с источниками данных и с использованием жидкости, но если не использовать жидкость, просто удалите это тоже!

Пример 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

...