2014-01-22 91 views
5
package com.sd.multitenncy; 

import java.util.HashMap; 
import java.util.Map; 

import javax.sql.DataSource; 

import org.apache.commons.dbcp.BasicDataSource; 
import org.hibernate.MultiTenancyStrategy; 
import org.hibernate.Session; 
import org.hibernate.cfg.AvailableSettings; 
import org.hibernate.cfg.Configuration; 
import org.hibernate.cfg.ImprovedNamingStrategy; 
import org.hibernate.engine.spi.SessionFactoryImplementor; 
import org.hibernate.service.ServiceRegistryBuilder; 
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider; 
import org.hibernate.service.spi.ServiceRegistryImplementor; 
import org.junit.Before; 
import org.junit.Test; 

import com.sd.config.MultiTenantConnectionProviderImpl; 
import com.sd.config.MultiTenantIdentifierResolver; 
import com.sd.entity.User; 

public class DatabaseBasedMultiTenancyTest 
{ 

    private ServiceRegistryImplementor serviceRegistry; 
    private SessionFactoryImplementor sessionFactory; 
    private MultiTenantIdentifierResolver currentTenantIdentifierResolver; 

    @Before 
    public void setUp() 
    { 
    Configuration config = new Configuration(); 
    config.getProperties().put(AvailableSettings.DIALECT,"org.hibernate.dialect.PostgreSQLDialect"); 
    config.getProperties().put(AvailableSettings.SHOW_SQL,"true"); 
    config.getProperties().put(AvailableSettings.FORMAT_SQL,"true"); 
    config.getProperties().put(AvailableSettings.HBM2DDL_AUTO,"update"); 
    config.getProperties().put(AvailableSettings.DEFAULT_SCHEMA,"public"); 
    config.getProperties().put(AvailableSettings.STATEMENT_BATCH_SIZE,"3000"); 
    config.getProperties().put(AvailableSettings.USE_SECOND_LEVEL_CACHE,"true"); 
    config.getProperties().put(AvailableSettings.CACHE_REGION_FACTORY,"org.hibernate.cache.ehcache.EhCacheRegionFactory"); 
    config.getProperties().put(AvailableSettings.ORDER_UPDATES,"true"); 
    config.getProperties().put(AvailableSettings.ORDER_INSERTS,"true"); 
    config.getProperties().put(AvailableSettings.MAX_FETCH_DEPTH,"1"); 
    config.setNamingStrategy(new ImprovedNamingStrategy()); 

    Map<String, DataSource> dataSources = new HashMap<String, DataSource>(); 
    DataSource dataSource1 = createDataSource("jdbc:postgresql://localhost/tenant1","postgres","postgres"); 
    DataSource dataSource2 = createDataSource("jdbc:postgresql://localhost/tenant2","postgres","postgres"); 

    dataSources.put("tenant1",dataSource1); 
    dataSources.put("tenant2",dataSource2); 

    MultiTenantConnectionProviderImpl multiTenantConnectionProvider = new MultiTenantConnectionProviderImpl(dataSources); 
    MultiTenantIdentifierResolver currentTenantIdentifierResolver = new MultiTenantIdentifierResolver(); 
    config.getProperties().put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER,multiTenantConnectionProvider); 
    config.getProperties().put(AvailableSettings.MULTI_TENANT,MultiTenancyStrategy.DATABASE); 
    config.getProperties().put(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER,currentTenantIdentifierResolver); 
    // JPA annotated classes 
    config.addPackage("com.sd.entity"); 
    config.addAnnotatedClass(User.class); 
    serviceRegistry = (ServiceRegistryImplementor)new ServiceRegistryBuilder().applySettings(config.getProperties()) 
     .addService(MultiTenantConnectionProvider.class,multiTenantConnectionProvider).buildServiceRegistry(); 

    sessionFactory = (SessionFactoryImplementor)config.buildSessionFactory(serviceRegistry); 
    } 

    private DataSource createDataSource(String url, String userName, String password) 
    { 
    final String driver = "org.postgresql.Driver"; 
    final String validationQuery = "SELECT 1 "; 

    final int minIdle = 3; 
    final int maxIdle = 3; 
    final int maxActive = 10; 
    final long maxWait = 6000; 
    final boolean removeAbandoned = true; 
    final boolean logAbandoned = true; 
    final boolean testOnBorrow = true; 
    final boolean testOnReturn = false; 
    final boolean testWhileIdle = false; 
    final long timeBetweenEvictionRunsMillis = 30000; 
    final long minEvictableIdleTimeMillis = 30000; 

    BasicDataSource dataSource = new BasicDataSource(); 
    dataSource.setDriverClassName(driver); 
    dataSource.setUsername(userName); 
    dataSource.setPassword(password); 
    dataSource.setValidationQuery(validationQuery); 
    dataSource.setUrl(url); 
    dataSource.setMaxIdle(minIdle); 
    dataSource.setMaxIdle(maxIdle); 
    dataSource.setMaxActive(maxActive); 
    dataSource.setMaxWait(maxWait); 
    dataSource.setRemoveAbandoned(removeAbandoned); 
    dataSource.setLogAbandoned(logAbandoned); 
    dataSource.setTestOnBorrow(testOnBorrow); 
    dataSource.setTestOnReturn(testOnReturn); 
    dataSource.setTestWhileIdle(testWhileIdle); 
    dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); 
    dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); 
    return dataSource; 
    } 

    protected Session getNewSession(String tenant) 
    { 
    return sessionFactory.withOptions().tenantIdentifier(tenant).openSession(); 
    } 

    @Test 
    public void testTableBasedMultiTenancy() 
    { 
    // try getting a new session explicitly providing the tenant identifier 
    Session session = getNewSession("tenant1"); 
    session.beginTransaction(); 
    User user = (User)session.load(User.class,1l); 
    System.out.println("************************* (" + user.getEmail() + ") ***********************************"); 
    session.getTransaction().commit(); 
    session.close(); 
    } 

} 

這段代碼在使用sessionFactory的hibernate中正常工作。我想將這段代碼轉換爲使用entityManager而不是sessionFactory,因爲我在HibernateJpaVendorAdapter中使用了spring數據jpa。Spring Data JPA,Hibernate Vendor,Multi-Tenancy和Postgres SQL

如果您有彈簧數據jpa和多租戶的任何示例/樣本(每個承租人單獨的數據庫),請分享或提供信息。

在此先感謝。您的幫助將受到高度讚賞。

回答

0

如果我的理解是正確的,你只需要創建持久化單元到你的persistence.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
version="2.0"> 
<persistence-unit name="test_persistance_unit" 
    transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 

    <properties> 
     <property name="hibernate.connection.url" 
      value="jdbc:postgresql://localhost:5432/db1" /> 
     <property name="hibernate.connection.username" value="postgres" /> 
     <property name="hibernate.connection.password" value="postgres" /> 
     <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" /> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" /> 
     <property name="hibernate.show-sql" value="false" /> 
     <property name="hibernate.jdbc.batch_size" value="1000"/>     
    </properties> 
</persistence-unit> 

<persistence-unit name="test_persistance_unit_2" 
    transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 

    <properties> 
     <property name="hibernate.connection.url" 
      value="jdbc:postgresql://localhost:5432/db2" /> 
     <property name="hibernate.connection.username" value="postgres" /> 
     <property name="hibernate.connection.password" value="postgres" /> 
     <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" /> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" /> 
     <property name="hibernate.show-sql" value="false" /> 
     <property name="hibernate.jdbc.batch_size" value="1000"/>     
    </properties> 
</persistence-unit> 

在此之後,你需要有和使用2 EntityManagerFactory的(每個D b)。

EntityManagerFactory emf = Persistence.createEntityManagerFactory("test_persistance_unit"); 
EntityManagerFactory emf2 = Persistence.createEntityManagerFactory("test_persistance_unit_2"); 
+1

我不想創建多個實體管理器工廠。考慮如果每個數據庫和500+數據庫中有500多個實體,那麼將使用多少內存。每個數據庫的結構相同,因此我可以使用一個實體管理器工廠。順便說一句,我已經完成了這一點。我會盡快發佈我的解決方案。 –

相關問題