4

我想通過自定義MultiTenantConnectionProvider獲得Spring-Data JPA與Hibernate一起工作。春季數據JPA與多租戶休眠

在我的配置下面的一切似乎工作。每次嘗試調用Repository方法時,我的MultiTenantConnectionProviderImpl類都會被調用。

主要問題是沒有辦法提供租戶標識符。 Spring-Data提供的Repository接口負責獲取Hibernate Session。

有什麼辦法可以爲Spring-Data提供租戶標識符嗎?或者是有什麼地方我們可以攔截創建休眠會話,所以我們可以適當地調用 sessionFactory.withOptions().tenantIdentifier(itendintifier).openSession();

這是我的Spring配置XML文件。我試圖儘可能保持它的骨幹。

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context.xsd 
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> 

    <context:annotation-config/> 
    <context:component-scan base-package="com.company"/> 
    <jpa:repositories base-package="com.company.repositories"/> 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="packagesToScan" value="com.company.entities"/> 
     <property name="dataSource" ref="dataSource"/> 
     <property name="jpaVendorAdapter"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
       <property name="showSql" value="true"/> 
      </bean> 
     </property> 
    </bean> 


    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory"/> 
    </bean> 

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2012Dialect</prop> 
       <prop key="hibernate.format_sql">true</prop> 
       <prop key="hibernate.multi_tenant_connection_provider">com.company.hibernate.MultiTenantConnectionProviderImpl</prop> 
       <prop key="hibernate.multiTenancy">DATABASE</prop> 
      </props> 
     </property> 
    </bean> 


    <tx:annotation-driven transaction-manager="transactionManager"/> 

    <!--Vendor specific properties here--> 
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver"/> 
     <property name="url" value="jdbc:jtds:sqlserver://localhost:1433/myDatabase"/> 
     <property name="username" value="username"/> 
     <property name="password" value="password"/> 
    </bean> 

</beans> 

回答

5

使用CurrentTenantIdentifierResolver

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="hibernateProperties"> 
     <map> 
      <entry key="hibernate.dialect" value="org.hibernate.dialect.SQLServer2012Dialect"> 
      <entry key="hibernate.format_sql" value="true"> 
      <entry key="hibernate.multi_tenant_connection_provider" value="com.company.hibernate.MultiTenantConnectionProviderImpl"> 
      <entry key="hibernate.multiTenancy" value="DATABASE"> 
      <!-- tenant resolver as spring bean --> 
      <entry key="hibernate.tenant_identifier_resolver" value-ref="currentTenantIdentifierResolver"/> 
     </map> 
    </property> 
</bean> 

<bean id="currentTenantIdentifierResolver" 
    class="com.xxx.CurrentTenantResolver"> 
</bean> 

簡單的承包者標識符解析會是這樣的:

public class CurrentTenantResolver implements CurrentTenantIdentifierResolver { 

    public String resolveCurrentTenantIdentifier() { 
     // retrieve tenant from logged in user 
     User usr = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal() ;  
     return usr.getTenantName(); 

    } 

    public boolean validateExistingCurrentSessions() { 
     return true; 
    } 

} 

記住上面的類是一個Spring bean,這樣你就可以自動連接任意Spring Bean(服務/道)就像普通的春天豆。

每當春天需要會話時,hibernate將從該bean中檢索租戶標識符。