gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 20:27:46 25 4
gpt4 key购买 nike

我创建了一个 Multi-Tenancy 逻辑,并将租户号存储在 ThreadLocal 中。当数据库属于同一类型(方言)时,一切都很好。在 spring boot 初始化期间,使用第一个(默认)数据源初始化 JPA 存储库(其 SQL 查询)。

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

这将创建租户类型的数据源。如果租户未知(在启动期间),它将采用租户 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();
}

}

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

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

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

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

最佳答案

(刚刚发布的)Jadira 5.0.0.GA 发生了变化,可以与 Multi-Tenancy 部署共存。免责声明:我维护 Jadira。

关于java - 如何使用具有相同存储库的多种数据源类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33085228/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com