mysql - Spring boot Multi-Tenancy ,一个租户连接到多个模式

标签 mysql spring hibernate spring-boot

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

租户 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

目前它是一个单租户应用程序,其中所有 3 个架构都已在 application.properties 中提及。所有数据库实例都具有相同的架构名称,但位于不同的数据库实例中。现在,有 3 个带有 @ 配置的独立配置文件,用于在应用程序启动时加载表。

我正在将此应用程序转换为 Multi-Tenancy 应用程序。实现具有单一架构的租户的 Multi-Tenancy 应用程序的步骤很清楚,但我有一个租户的多个架构。因此,问题是在实现 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);
    } 

提前致谢, 谢尔茨

最佳答案

这只是给出的方法,并不完全是解决方案

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

public class ClientDataSourceRouter
  extends AbstractRoutingDataSource {

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

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

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

@配置 公共(public)类 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

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

Multi-Tenancy 模型 有几种模型可以在应用程序中实现 Multi-Tenancy :

  • 每个租户的数据库 每个租户都有自己的数据库,并且与其他租户隔离。
  • 共享数据库,独立架构(这就是我们正在寻找的)

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

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

示例:

@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

关于mysql - Spring boot Multi-Tenancy ,一个租户连接到多个模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52199973/

相关文章:

spring - 使用 ControllerAdvice 添加模型属性

java - Spring MVC + Hibernate + JSON post方法保存到数据库

xml - 错误 : No persistence units parsed from {classpath*:META-INF/persistence. xml}

hibernate - Grails:乐观锁定,StaleObjectStateException与Spring Security session 中的域,更新计数器

asp.net - 将 varchar 转换为 int SQl server 2005

mysql - 数组内连接的使用

php - 大写 FROM 导致错误 1064

mysql - 选择从上个月开始的所有行

spring - AuthenticationCredentialsNotFoundException : An Authentication object was not found in the SecurityContext

java - 通过 JPA 为 MySQL 节省时间