spring 启用多个数据源时,TenantConnectionProvider找不到租户

jq6vz3qz  于 2023-11-16  发布在  Spring
关注(0)|答案(1)|浏览(162)

我正在创建一个使用多租户的SpringKotlin应用程序。我想向我的应用程序添加第二个数据源。
使用Sping Boot JPA自动配置,多租户可以很好地处理单个数据源。我不需要创建任何DatasourceConfiguration类。
由于我想添加第二个数据源,我不能再依赖自动配置,而是必须为每个数据源创建配置类:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    transactionManagerRef = "transactionManagerA",
    entityManagerFactoryRef = "entityManagerFactoryA",
    basePackages = ["com.myapp.repository.a"]
)
class DataSourceConfigA {
}

字符串
多租户是由TenantConnectionProvider类启用的,如下所示:

@Component
class TenantConnectionProvider :
    MultiTenantConnectionProvider,
    HibernatePropertiesCustomizer {

    @Autowired
    private lateinit var datasource: DataSource

    override fun getAnyConnection(): Connection = datasource.connection
   
    ...
}


由于我添加了DataSourceConfig类来配置我的多个数据源,TenantConnectionProvider中的datasource不再自动连接,并且使用多租户的数据库查询失败。
我得到以下错误:

lateinit property dataSource has not been initialized


为什么禁用JPA autoconfig会破坏TenantConfigProvider中的JPA自动配置?
如何在Sping Boot Kotlin应用程序中组合合并多租户和多个数据源?

d4so4syb

d4so4syb1#

看看为应用程序提供TenantConnectionProvider的MultiTenantConnectionProviderInitializor类。
它从application.yml中搜索hibernate.multi_tenant_connection_provider配置值。如果能找到,则检查该类是否是MultiTenantConnectionProvider的示例,然后返回该类。
在上面的代码中,配置是一个String(com.myapp.config.TenantConnectionProvider),发起者最终尝试用implClass.newInstance()示例化该类,而没有自动装配任何bean。datasource没有初始化,任何未来的连接都会失败。
在您的JavaScript配置类中,您可以覆盖hibernate.multi_tenant_connection_provider属性以使用TenantConnectionProvider的示例,该示例使用注入的bean,如下所示:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    transactionManagerRef = "transactionManagerA",
    entityManagerFactoryRef = "entityManagerFactoryA",
    basePackages = ["com.myapp.repository.a"]
)
class DataSourceConfigA {
    
    ...

    @Bean
    @Primary
    fun tenantConnectionProvider(): MultiTenantConnectionProvider = TenantConnectionProvider()
    
    @Bean(name = ["entityManagerFactoryA"])
    @Primary
    fun postgresEntityManagerFactory(
        dataSource: DataSource,
        builder: EntityManagerFactoryBuilder
    ): LocalContainerEntityManagerFactoryBean {
        return builder.dataSource(dataSource)
            .packages("com.myapp.domain.a")
            // Overwrite hibernate.multi_tenant_connection_provider to use a class instance
            .properties(mapOf(Pair("hibernate.multi_tenant_connection_provider", tenantConnectionProvider())))
            .build()
    }
    
    ...

}

字符串
这将导致启动器使用您自己的示例,而不是尝试示例化没有自动连接bean的类。

相关问题