Spring Boot + Spring Data 多租户

Posted

技术标签:

【中文标题】Spring Boot + Spring Data 多租户【英文标题】:Spring Boot + Spring Data with multi tenancy 【发布时间】:2015-01-10 00:12:57 【问题描述】:

是否可以将 Spring Boot 配置为使用 MultiTenantConnectionProvider 以便我系统的每个客户端都连接到自己的私有数据库?

具体来说,我希望使用内置的休眠支持来支持多租户:

http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html_single/#d5e4561

这是我所追求的那种配置的一个例子,但我不知道如何在 Spring Boot 设置中使用它:

Manage Connection Pooling in multi-tenant web app with Spring, Hibernate and C3P0

我已经尝试将这些属性添加到application.properties

spring.jpa.hibernate.multiTenancy=DATABASE
spring.jpa.hibernate.tenant_identifier_resolver=com.mystuff.MyCurrentTenantIdentifierResolver
spring.jpa.hibernate.multi_tenant_connection_provider=com.mystuff.MyMultiTenantConnectionProviderImplX

我也尝试编写自己的 CurrentTenantIdentifierResolverMultiTenantConnectionProvider 并尝试从我的主要 @Configuration bean 中提供这些:

@Bean
public CurrentTenantIdentifierResolver currentTenantIdentifierResolver() 
    return new CurrentTenantIdentifierResolver() 
        public String resolveCurrentTenantIdentifier() 
            // this is never called ...
        
        public boolean validateExistingCurrentSessions() 
            // this is never called ...
        
    ;


@Bean
public MultiTenantConnectionProvider multiTenantConnectionProvider() 
    return new AbstractMultiTenantConnectionProvider() 
        protected ConnectionProvider getAnyConnectionProvider() 
            // this is never called ...
        
        protected ConnectionProvider selectConnectionProvider(String s) 
            // this is never called ...
        
    ;

这些似乎都没有任何影响,所以我的问题是如何让 spring-boot / spring-data 使用这些多租户类?

感谢您的帮助!

【问题讨论】:

查看我的问题here。我使用LocalContainerEntityManagerFactoryBean,它可以工作。但我并不完全理解这与.ymlor@ 之间的区别987654331@. 我同意@M.Deinum ,在yml hibernate 控制mulitTenantConnectionProviderCurrentTenantIdentifierResolver 的生命周期。但我不知道为什么。 【参考方案1】:

可以使用application.properties 中的spring.jpa.properties 属性设置未定义的JPA/Hibernate 的Any property。

您链接到的示例具有 3 个多租户属性:

<prop key="hibernate.multiTenancy">SCHEMA</prop>
<prop key="hibernate.tenant_identifier_resolver">com.webapp.persistence.utility.CurrentTenantContextIdentifierResolver</prop>
<prop key="hibernate.multi_tenant_connection_provider">com.webapp.persistence.utility.MultiTenantContextConnectionProvider</prop>

转换为 Spring Boot 的将是 application.properties 文件中的以下属性。

spring.jpa.properties.hibernate.multiTenancy=SCHEMA
spring.jpa.properties.hibernate.tenant_identifier_resolver=com.mystuff.MyCurrentTenantIdentifierResolver
spring.jpa.properties.hibernate.multi_tenant_connection_provider=com.webapp.persistence.utility.MultiTenantContextConnectionProvider

针对您的情况(如您的问题所述)。

spring.jpa.properties.hibernate.multiTenancy=DATABASE
spring.jpa.properties.hibernate.tenant_identifier_resolver=com.webapp.persistence.utility.CurrentTenantContextIdentifierResolver 
spring.jpa.properties.hibernate.multi_tenant_connection_provider=com.mystuff.MyMultiTenantConnectionProviderImplX

它不适用于 Spring 管理的 bean,因为休眠控制这些实例的生命周期。

有关更多属性,请参阅 Spring Boot reference guide。

【讨论】:

谢谢,我错过了“.properties”。位(事后看来,docco很清楚,但我第一次读到它时确实错过了它)。正如您所强调的那样,现在围绕生命周期的东西有点挑战。特别是从 ConnectionProvider 中访问其他 Spring 服务。我已经尝试过保持对我需要的服务的静态引用的方法,但是首先创建了休眠的东西,所以当我需要它时它是空的。回退是在这些类中不使用 Spring 服务,但这会使代码变得混乱。如果您对此有任何想法,我很想听听。 虽然你可以使用ContextLoader.getCurrentWebApplicationContext 来访问上下文并进行查找,虽然有点hacky。或者创建一个帮助类,您可以使用它来检索服务。 是的,谢谢 - 我尝试了这两种方法,但无论 Spring Boot 做什么都会导致 MultiTenantConnectionProvider 在上下文存在之前被实例化,因此 ContextLoader。首次调用 getAnyConnectionProvider() 时,getCurrentWebApplicationContext() 为空,此时辅助类也找不到服务。我想我只是无法从 MultiTenantConnectionProvider 中使用 Spring 服务。可耻,但不是世界末日。非常感谢您的帮助,非常感谢! 还尝试使用Spring Data JPA 使用每个租户策略从单租户迁移到多租户,但@Service 实例和@Transactional 方法看起来确实不支持... 不,这与此无关。

以上是关于Spring Boot + Spring Data 多租户的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot + spring-data-redis

Spring Boot 整合Spring Data JPA

Spring Boot 在使用 solrj 而不是 spring-boot-starter-data-solr 时会爆炸

spring boot系列spring boot 配置spring data jpa (查询方法)

Spring boot集成spring-boot-starter-data-jpa环境搭建

spring boot -spring data-redis