2016-12-24 72 views
1

我有,其中,用戶註冊一個新的數據庫,爲他們創造了一個場景。註冊過程完成後,需要將該數據庫添加到MultiTenantConnectionProvider(連接池)中。一切正常,但無法將數據源動態添加到MultiTenantConnectionProvider。春季多租戶:數據源添加到MultiTenantConnectionProvider動態當用戶添加

Hibernate的配置爲多租戶:

 <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
       <prop key="hibernate.multiTenancy">DATABASE</prop> 
       <prop key="hibernate.tenant_identifier_resolver">com.company.multitenancy.MyCurrentTenantIdentifierResolverImpl 
       </prop> 
       <prop key="hibernate.multi_tenant_connection_provider">com.company.multitenancy.MyMultiTenantConnectionProvider 
       </prop> 
      </props> 
     </property> 

代碼MyMultiTenantConnectionProvider:

package com.company.multitenancy; 

import java.sql.DriverManager; 
import java.sql.ResultSet; 
import java.sql.Statement; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 

import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider; 
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;  
import com.termbreak.constant.ConstantStrings; 

public class MyMultiTenantConnectionProvider extends 
     AbstractMultiTenantConnectionProvider { 
    private static final long serialVersionUID = -8669630427906544663L; 
    private HashMap<String, ConnectionProviderImpl> connProviderMap = new HashMap<String, ConnectionProviderImpl>(); 

    public MyMultiTenantConnectionProvider() { 
     List<String> providerNames = new ArrayList<String>(); 
     providerNames.add(ConstantStrings.DEFAULT_TENANT_ID); 
     try { 
      String sqlUrl = "jdbc:mysql://localhost:3306/"+ConstantStrings.DEFAULT_TENANT_ID; 
      Class.forName("com.mysql.jdbc.Driver"); 
      java.sql.Connection conn = DriverManager.getConnection(sqlUrl, 
        "root", "root"); 
      Statement st = conn.createStatement(); 
      ResultSet rs = st 
        .executeQuery("select DISTINCT TENANT_ID from User"); 
      while (rs.next()) { 
       String tenantId = rs.getString(1); 
       providerNames.add(tenantId); 
      } 
      conn.close(); 
     } catch (Exception e) { 
      System.err.println("Got an exception! "); 
      System.err.println(e.getMessage()); 
     } 
     for (String providerName : providerNames) { 
      connProviderMap.put(providerName, new ConnectionProviderImpl(
        providerName)); 
     } 
    } 

    public ConnectionProvider getAnyConnectionProvider() { 
     System.out 
       .println("inside MultiTenantConnectionProvider::getAnyConnectionProvider"); 
     return connProviderMap.get(ConstantStrings.DEFAULT_TENANT_ID); 
    } 

    public ConnectionProvider selectConnectionProvider(String tenantId) { 
     ConnectionProvider connectionProvider = connProviderMap.get(tenantId); 
     if (connectionProvider == null) 
      connectionProvider = new ConnectionProviderImpl(ConstantStrings.DEFAULT_TENANT_ID); 
     return connectionProvider; 
    } 
} 

代碼MyCurrentTenantIdResolver:

package com.company.multitenancy; 

import org.hibernate.context.spi.CurrentTenantIdentifierResolver; 

import com.termbreak.constant.ConstantStrings; 

public class MyCurrentTenantIdentifierResolverImpl implements 
     CurrentTenantIdentifierResolver { 
    public ThreadLocal<String> _tenantIdentifier = new ThreadLocal<String>(); 
    public String DEFAULT_TENANT_ID = ConstantStrings.DEFAULT_TENANT_ID; 

    public String resolveCurrentTenantIdentifier() { 
     System.out.println("from inside resolveCurrentTenantIdentifier...."); 
     String tenantId = _tenantIdentifier.get(); 
     if (tenantId == null) 
      tenantId = DEFAULT_TENANT_ID; 
     System.out.println("threadlocal tenant id =" + tenantId); 
     return tenantId; 
    } 

    public boolean validateExistingCurrentSessions() { 
     return true; 
    } 

} 

代碼MyConnectionProviderImpl:

package com.company.multitenancy; 

import java.sql.Connection; 
import java.sql.SQLException; 

import org.apache.commons.dbcp2.BasicDataSource; 
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; 

public class ConnectionProviderImpl implements ConnectionProvider { 
    private static final long serialVersionUID = -8926112316994338537L; 
    private BasicDataSource basicDataSource; 

    public ConnectionProviderImpl(String database){ 
     //this should be read from properties file 
     basicDataSource = new BasicDataSource(); 
     basicDataSource.setDriverClassName("com.mysql.jdbc.Driver"); 
     basicDataSource.setUrl("jdbc:mysql://localhost:3306/"+database); 
     basicDataSource.setUsername("root"); 
     basicDataSource.setPassword("root"); 
     basicDataSource.setInitialSize(2); 
    } 
    public boolean isUnwrappableAs(Class arg0) { 
     return false; 
    } 
    public Object unwrap(Class arg0) { 
     return null; 
    } 
    public void closeConnection(Connection arg0) throws SQLException { 
     arg0.close(); 
    } 
    public Connection getConnection() throws SQLException { 
     return basicDataSource.getConnection(); 
    } 
    public boolean supportsAggressiveRelease() { 
     return false; 
    } 
} 

要連接到特定租戶我使用:

sessionFactory.withOptions().tenantIdentifier(tenantId).openSession(); 

回答

0

你的配置似乎是正確的,除了實施ConnectionProviderImpl的。在這個實現中,你需要爲租戶標識符提供hibernate。你將需要實施AbstractDataSourceBasedMultiTenantConnectionProviderImpl,要麼依賴於Hibernate的版本使用的是重載的getConnection()或selectDataSource()。我建議你按照Hibernate的用戶指南https://docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/ch16.html例16.3和這個帖子http://www.ticnfae.co.uk/blog/2014/07/16/hibernate-multi-tenancy-with-spring/

+0

感謝您的快速回復,每一件事情正在完善與此代碼,當用戶註冊爲該用戶創建一個新的數據庫,並生成一個新的租戶ID我需要添加我面臨的,現在唯一的問題是這個租戶ID到連接池,我無法。任何指針將幫助 –

+0

而不是直接實現的ConnectionProvider,您可以通過擴展AbstractDataSourceBasedMultiTenantConnectionProviderImpl試圖重寫selectDataSource()。 MyCurrentTenantIdentifierResolverImpl#resolveCurrentTenantIdentifier()返回承租人標識符。此租戶標識符在AbstractDataSourceBasedMultiTenantConnectionProviderImpl#selectDataSource(字符串tenantIdentifier)使用。 –