Spring Boot多租户,其中一个租户连接到多个架构

时间:2018-09-06 08:41:34

标签: mysql spring hibernate spring-boot

我正在创建一个应支持多租户,独立数据库方法的Spring Boot应用程序。每个租户将使用多个架构,并且将从某个配置文件动态加载它。租户和架构将是这样,

租户1:

url : dbc:mysql://dns1/abc_schema
username : sa
password : sa

url : dbc:mysql://dns1/pqr_schema
username : sa
password : sa

url : dbc:mysql://dns1/xyz_schema
username : sa
password : sa

租户2:

url : dbc:mysql://dns2/abc_schema
username : sa
password : sa

url : dbc:mysql://dns2/pqr_schema
username : sa
password : sa

url : dbc:mysql://dns2/xyz_schema
username : sa
password : sa

当前是单个租户应用程序,在application.properties中提到了所有3个模式。所有数据库实例都具有相同的架构名称,但是在不同的数据库实例中。现在,有3个带有@配置的单独配置文件,可在应用程序启动时加载表。

我正在将此应用程序转换为多租户应用程序。使用具有单个模式的租户实现多租户应用程序的步骤很清楚,但是我有一个租户具有多个模式。因此,问题是实现AbstractDataSourceBasedMultiTenantConnectionProviderImpl类时,selectDataSource()函数将返回单个数据源。但是如何传递多个模式呢?

@Override
    protected DataSource selectDataSource(String tenantIdentifier) {
        if (isInitialLoad) {
            isInitialLoad = false;
            TenantDataSource tenantDataSource = context.getBean(TenantDataSource.class);
            map.putAll(tenantDataSource.getAll());
        }
        return map.get(tenantIdentifier);
    } 

预先感谢, 舍尔兹

1 个答案:

答案 0 :(得分:0)

这只是给定的方法,并非完全解决方案

定义路由器,如下所示,您可以在配置中进行设置

public class ClientDataSourceRouter
  extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return ClientDatabaseContextHolder.getClientDatabase();
    }
}

我们需要一个上下文到DataSource对象的映射来配置AbstractRoutingDataSource。如果没有设置上下文,我们还可以指定要使用的默认数据源。

我们使用的数据源可以来自任何地方,但通常可以在运行时创建或使用JNDI查找:

@配置 公共类RoutingTestConfiguration {

@Bean
public DataSource clientDatasource() {
    Map<Object, Object> targetDataSources = new HashMap<>();
    DataSource clientADatasource = clientADatasource();
    DataSource clientBDatasource = clientBDatasource();
    targetDataSources.put(ClientDatabase.CLIENT_A, 
      clientADatasource);
    targetDataSources.put(ClientDatabase.CLIENT_B, 
      clientBDatasource);

    ClientDataSourceRouter clientRoutingDatasource 
      = new ClientDataSourceRouter();
    clientRoutingDatasource.setTargetDataSources(targetDataSources);
    clientRoutingDatasource.setDefaultTargetDataSource(clientADatasource);
    return clientRoutingDatasource;
}

// ...

}

check out more information - baeldung

定义了另一个解决方案,如下所示

多租户模型 有几种模型可以在应用程序中实现多租户:

  • 每个租户的数据库 每个租户都有自己的数据库,并且与其他租户隔离。
  • 共享数据库,独立模式(这是我们想要的)

所有租户共享一个数据库,但是具有自己的数据库架构和自己的表。

  • 共享数据库,共享架构 所有租户共享一个数据库和表。每个表都有一个带有“租户标识符”的列,该列显示该行的所有者。

示例:

@Bean
    public DataSource dataSource() {

        AbstractRoutingDataSource dataSource = new TenantAwareRoutingSource();

        Map<Object,Object> targetDataSources = new HashMap<>();

        targetDataSources.put("TenantOne", tenantOne());
        targetDataSources.put("TenantTwo", tenantTwo());

        dataSource.setTargetDataSources(targetDataSources);

        dataSource.afterPropertiesSet();

        return dataSource;
    }

    public DataSource tenantOne() {

        HikariDataSource dataSource = new HikariDataSource();

        dataSource.setInitializationFailTimeout(0);
        dataSource.setMaximumPoolSize(5);
        dataSource.setDataSourceClassName("org.postgresql.ds.PGSimpleDataSource");
        dataSource.addDataSourceProperty("url", "jdbc:postgresql://127.0.0.1:5432/sampledb");
        dataSource.addDataSourceProperty("user", "philipp");
        dataSource.addDataSourceProperty("password", "test_pwd");
 **we need to find datasource.setschema is exist or not**
        return dataSource;
    }

    public DataSource tenantTwo() {

        HikariDataSource dataSource = new HikariDataSource();

        dataSource.setInitializationFailTimeout(0);
        dataSource.setMaximumPoolSize(5);
        dataSource.setDataSourceClassName("org.postgresql.ds.PGSimpleDataSource");
        dataSource.addDataSourceProperty("url", "jdbc:postgresql://127.0.0.1:5432/sampledb1");
        dataSource.addDataSourceProperty("user", "philipp");
        dataSource.addDataSourceProperty("password", "test_pwd");
** we need to find datasource.setschema is exist or not**
        return dataSource;
    }

或者也只有一种选择

一个租户

spring.datasource.first.url=jdbc:postgresql://my_url:my_port/my_other_stuff
spring.datasource.first.username=my_user_name
spring.datasource.first.password=my_password
spring.datasource.first.driver-class-name=org.postgresql.Driver
spring.datasource.first.schema=A

租户二

spring.source.second.url=jdbc:postgresql://my_url:my_port/my_other_stuff
spring.source.second.username=my_user_name
spring.source.second.password=my_password
spring.source.second.driver-class-name=org.postgresql.Driver
spring.source.second.schema = B

然后为每个属性创建PropertySource类,然后在spring之前对其进行设置,然后就可以使用它们

 @ConfigurationProperties(prefix = "datasource.first")
@Bean
@Primary
public DataSource dataSource() {
    return DataSourceBuilder
        .create()
        .build();
}

也请检查此链接 enter link description here