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();
}
}
Dieser Code funktioniert einwandfrei mit Hibernate mit SessionFactory. Ich möchte diesen Code konvertieren, um EntityManager anstelle von SessionFactory zu verwenden, da ich Springdaten jpa mit HibernateJpaVendorAdapter verwende.Spring Data JPA, Hibernate-Anbieter, Mandantenfähigkeit und Postgres SQL
Wenn Sie ein Beispiel/Beispiel von Spring Data jpa und Multi-Tenancy (separate Datenbank für jeden Mieter) haben, bitte teilen oder Informationen bereitstellen.
Dank Im Voraus. Ihre Hilfe wird sehr geschätzt.
Ich möchte nicht mehrere Entity Manager Factory erstellen. Überlegen Sie, ob ich mehr als 500 Entitäten pro Datenbank und 500+ Datenbank habe und wieviel Speicher verwendet wird. Die Struktur jeder Datenbank ist dieselbe, so dass ich eine Entity Manager Factory verwenden kann. Übrigens habe ich damit fertig. Ich werde meine Lösung so schnell wie möglich veröffentlichen. –