繁体   English   中英

如何使用具有相同存储库的多个数据源类型?

[英]How to use multiple datasources types with the same repositories?

我创建了一个多租户逻辑,我将租户号码存储在ThreadLocal 当数据库具有相同类型(方言)时,一切都很好。 在Spring启动初始化期间,JPA存储库使用第一个(和默认)数据源进行初始化(其SQL查询)。

但是,当我配置了Oracle和Postgres数据库时,spring boot仍会尝试使用第一个租户数据源的方言进行查询,这是一个非常大的问题,因为数据库类型的方言不同。

这将创建租户类型的dataSource。 如果租户尚未知晓(在启动期间),则需要租户-1。

@Bean
public DataSource dataSource() throws SQLException {
    String tenant1 = "tenant-1";
    String tenant2 = "tenant-2";

    CustomRoutingDataSource customRoutingDataSource = new CustomRoutingDataSource();

    final DataSource tenant1DataSource = createDataSourceForTenant(tenant1);
    final DataSource tenant2DataSource = createDataSourceForTenant(tenant2);

    HashMap<Object, Object> targetDataSources = new HashMap<>();
    targetDataSources.put(tenant1.toUpperCase(), tenant1DataSource);
    targetDataSources.put(tenant2.toUpperCase(), tenant2DataSource);

    customRoutingDataSource.setTargetDataSources(targetDataSources);
    return customRoutingDataSource;
}

这将静态地创建数据源 - 当我解决问题时,将在稍后从JNDI源动态提取替换:

private DataSource createDataSourceForTenant(String tenant) throws SQLException {
    final DriverManagerDataSource dataSource = new DriverManagerDataSource();

    final LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
    factoryBean.setDataSource(dataSource);
    factoryBean.setPackagesToScan(new String[]{"entities"});

    if (tenant.equalsIgnoreCase("tenant-1")) {
        dataSource.setDriverClassName("org.postgresql.Driver");
        dataSource.setUrl("jdbc:postgresql://localhost:5433/importservices");
        dataSource.setUsername("test");
        dataSource.setPassword("test");

        factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        factoryBean.afterPropertiesSet();
    }

    if (tenant.equalsIgnoreCase("tenant-2")) {
        dataSource.setDriverClassName("org.hibernate.dialect.Oracle10gDialect");
        dataSource.setUrl("jdbc:oracle:thin:@//oracle11:1521/deviso");
        dataSource.setUsername("test");
        dataSource.setPassword("test");

        factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        factoryBean.afterPropertiesSet();
    }

    factoryBean.destroy();
    return dataSource;
}

定制数据库路由。 当租户不可用时(启动期间),getTenant返回默认值(1)。

public class CustomRoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return "TENANT-"+TenantThreadLocal.getTenant();
    }

}

现在,如果我有默认的tenant = 1,则spring boot会在启动时初始化并为实体创建特定于PostgreSQL的查询。 如果我在运行时作为租户2(Oracle方言)访问它,我得到:

java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended

因为Spring JPA用PostgreSQL方言初始化了JPA存储库。 所以可能性是:

1)每个租户有多个EntityManagers - 不太舒服,因为租户是动态管理的
2) hibernate中的多租户支持 - 实际上我无法实现这一点,因为jadira框架在多租户支持方面存在一些问题,并且在2周之前仍未修复并等待修复
3) ??

(刚刚发布的)Jadira 5.0.0.GA中的更改与多租户部署共存。 免责声明:我维持Jadira。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM