BAEL-399: A Guide to Multitenancy in Hibernate 5 (#3235)
* BAEL-399: A Guide to Multitenancy in Hibernate 5 * Removed unused properties in profile 2
This commit is contained in:
parent
13d47f0873
commit
85f12cd254
|
@ -41,7 +41,7 @@
|
|||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.194</version>
|
||||
<version>1.4.196</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
package com.baeldung.hibernate;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
|
||||
import com.baeldung.hibernate.pojo.Supplier;
|
||||
|
||||
/**
|
||||
* Hello world!
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
// NOTE: this is just for boostrap testing for multitenancy.
|
||||
System.out.println("Checking the system.");
|
||||
SessionFactory sessionFactory = HibernateMultiTenantUtil.getSessionFactory();
|
||||
Session currentSession = sessionFactory.withOptions().tenantIdentifier("h2db1").openSession();
|
||||
Transaction transaction = currentSession.getTransaction();
|
||||
transaction.begin();
|
||||
currentSession.createCriteria(Supplier.class).list().stream().forEach(System.out::println);
|
||||
transaction.commit();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package com.baeldung.hibernate;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
|
||||
public class ConfigurableMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider {
|
||||
|
||||
private final Map<String, ConnectionProvider> connectionProviderMap =
|
||||
new HashMap<>();
|
||||
|
||||
|
||||
public ConfigurableMultiTenantConnectionProvider(
|
||||
Map<String, ConnectionProvider> connectionProviderMap) {
|
||||
this.connectionProviderMap.putAll( connectionProviderMap );
|
||||
}
|
||||
@Override
|
||||
protected ConnectionProvider getAnyConnectionProvider() {
|
||||
System.out.println("Any");
|
||||
return connectionProviderMap.values().iterator().next();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
|
||||
System.out.println("Specific");
|
||||
return connectionProviderMap.get( tenantIdentifier );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection(String tenantIdentifier) throws SQLException {
|
||||
Connection connection = super.getConnection(tenantIdentifier);
|
||||
// uncomment to see option 2 for SCHEMA strategy.
|
||||
//connection.createStatement().execute("SET SCHEMA '" + tenantIdentifier + "'");
|
||||
return connection;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
package com.baeldung.hibernate;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
import com.baeldung.hibernate.pojo.Supplier;
|
||||
|
||||
public class HibernateMultiTenantUtil {
|
||||
private static SessionFactory sessionFactory;
|
||||
private static Map<String, ConnectionProvider> connectionProviderMap = new HashMap<>();
|
||||
private static final String[] tenantDBNames = { "mydb1", "mydb2" };
|
||||
|
||||
public static SessionFactory getSessionFactory() throws UnsupportedTenancyException, IOException {
|
||||
if (sessionFactory == null) {
|
||||
// Configuration configuration = new Configuration().configure();
|
||||
ServiceRegistry serviceRegistry = configureServiceRegistry();
|
||||
sessionFactory = makeSessionFactory(serviceRegistry);
|
||||
|
||||
}
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
private static SessionFactory makeSessionFactory(ServiceRegistry serviceRegistry) {
|
||||
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
|
||||
for (Class annotatedClasses : getAnnotatedClasses()) {
|
||||
metadataSources.addAnnotatedClass(annotatedClasses);
|
||||
}
|
||||
|
||||
Metadata metadata = metadataSources.buildMetadata();
|
||||
return metadata.getSessionFactoryBuilder()
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
private static Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] { Supplier.class };
|
||||
}
|
||||
|
||||
private static ServiceRegistry configureServiceRegistry() throws UnsupportedTenancyException, IOException {
|
||||
|
||||
// Properties properties = configuration.getProperties();
|
||||
Properties properties = getProperties();
|
||||
|
||||
connectionProviderMap = setUpConnectionProviders(properties, tenantDBNames);
|
||||
properties.put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, new ConfigurableMultiTenantConnectionProvider(connectionProviderMap));
|
||||
|
||||
return new StandardServiceRegistryBuilder().applySettings(properties)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static Properties getProperties() throws IOException {
|
||||
Properties properties = new Properties();
|
||||
URL propertiesURL = Thread.currentThread()
|
||||
.getContextClassLoader()
|
||||
.getResource("hibernate-multitenancy.properties");
|
||||
FileInputStream inputStream = new FileInputStream(propertiesURL.getFile());
|
||||
properties.load(inputStream);
|
||||
System.out.println("LOADED PROPERTIES FROM hibernate.properties");
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static Map<String, ConnectionProvider> setUpConnectionProviders(Properties properties, String[] tenantNames) throws UnsupportedTenancyException {
|
||||
Map<String, ConnectionProvider> providerMap = new HashMap<>();
|
||||
for (String tenant : tenantNames) {
|
||||
DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl();
|
||||
|
||||
String tenantStrategy = properties.getProperty("hibernate.multiTenancy");
|
||||
System.out.println("Strategy:" + tenantStrategy);
|
||||
properties.put(Environment.URL, tenantUrl(properties.getProperty(Environment.URL), tenant, tenantStrategy));
|
||||
System.out.println("URL:" + properties.getProperty(Environment.URL));
|
||||
connectionProvider.configure(properties);
|
||||
System.out.println("Tenant:" + tenant);
|
||||
providerMap.put(tenant, connectionProvider);
|
||||
|
||||
}
|
||||
System.out.println("Added connections for:");
|
||||
providerMap.keySet()
|
||||
.stream()
|
||||
.forEach(System.out::println);
|
||||
return providerMap;
|
||||
}
|
||||
|
||||
private static Object tenantUrl(String originalUrl, String tenant, String tenantStrategy) throws UnsupportedTenancyException {
|
||||
if (tenantStrategy.toUpperCase()
|
||||
.equals("DATABASE")) {
|
||||
return originalUrl.replace(DEFAULT_DB_NAME, tenant);
|
||||
} else if (tenantStrategy.toUpperCase()
|
||||
.equals("SCHEMA")) {
|
||||
return originalUrl + String.format(SCHEMA_TOKEN, tenant);
|
||||
} else {
|
||||
throw new UnsupportedTenancyException("Not yet supported");
|
||||
}
|
||||
}
|
||||
|
||||
public static final String SCHEMA_TOKEN = ";INIT=CREATE SCHEMA IF NOT EXISTS %1$s\\;SET SCHEMA %1$s";
|
||||
public static final String DEFAULT_DB_NAME = "mydb1";
|
||||
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package com.baeldung.hibernate.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface GenericDao<T> {
|
||||
|
||||
void save (T entity);
|
||||
void delete (T Entity);
|
||||
T findByName(String name);
|
||||
List<T> findAll();
|
||||
void populate();
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package com.baeldung.hibernate.dao;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.Expression;
|
||||
|
||||
import com.baeldung.hibernate.pojo.Supplier;
|
||||
|
||||
public class SupplierDao implements GenericDao<Supplier>{
|
||||
private SessionFactory sessionFactory;
|
||||
private String tenant;
|
||||
|
||||
public SupplierDao(SessionFactory sessionFactory, String tenant) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.tenant = tenant;
|
||||
populate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Supplier entity) {
|
||||
Session session = sessionFactory.withOptions().tenantIdentifier(tenant).openSession();
|
||||
session.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Supplier supplier) {
|
||||
Session session = sessionFactory.withOptions().tenantIdentifier(tenant).openSession();
|
||||
session.delete(supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Supplier findByName(String name) {
|
||||
Session session = sessionFactory.withOptions().tenantIdentifier(tenant).openSession();
|
||||
List<Supplier> fetchedSuppliers = session.createCriteria(Supplier.class).add(Expression.eq("name", name)).list();
|
||||
if (fetchedSuppliers.size()>0) {
|
||||
return fetchedSuppliers.get(0);
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Supplier> findAll() {
|
||||
Session session = sessionFactory.withOptions().tenantIdentifier(tenant).openSession();
|
||||
return session.createCriteria(Supplier.class).list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate() {
|
||||
System.out.println("Init DB1");
|
||||
Session session = sessionFactory.withOptions().tenantIdentifier(tenant).openSession();
|
||||
Transaction transaction = session.getTransaction();
|
||||
|
||||
transaction.begin();
|
||||
session.createSQLQuery("DROP ALL OBJECTS").executeUpdate();
|
||||
session
|
||||
.createSQLQuery(
|
||||
"create table Supplier (id integer generated by default as identity, country varchar(255), name varchar(255), primary key (id))")
|
||||
.executeUpdate();
|
||||
Supplier genertedSupplier = generateEntityForTenant(tenant);
|
||||
System.out.println("Inserting Supplier"+genertedSupplier);
|
||||
save (genertedSupplier);
|
||||
|
||||
}
|
||||
|
||||
private Supplier generateEntityForTenant(String forTenant) {
|
||||
if (forTenant.equals("mydb1")) {
|
||||
return new Supplier ("John","USA");
|
||||
}
|
||||
return new Supplier ("Miller","UK");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
package com.baeldung.hibernate.pojo;
|
||||
// Generated Feb 9, 2017 11:31:36 AM by Hibernate Tools 5.1.0.Final
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
|
||||
/**
|
||||
* Suppliers generated by hbm2java
|
||||
*/
|
||||
@Entity(name = "Supplier")
|
||||
@Table(name ="Supplier")
|
||||
public class Supplier implements java.io.Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Integer id;
|
||||
private String name;
|
||||
private String country;
|
||||
|
||||
public Supplier() {
|
||||
}
|
||||
|
||||
public Supplier(String name, String country) {
|
||||
this.name = name;
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return this.country;
|
||||
}
|
||||
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuffer().append("[").append(id).append(",").append(name).append(",").append(country).append("]").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return name.equals(((Supplier) obj).getName());
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package com.baeldung.hibernate;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.hibernate.dao.SupplierDao;
|
||||
import com.baeldung.hibernate.pojo.Supplier;
|
||||
|
||||
import static org.junit.Assert.assertNull;;
|
||||
|
||||
public class MultiTenantDaoHibernateIntegrationTest {
|
||||
@Test
|
||||
public void givenDBMode_whenFetchingSuppliersByName_thenChecking() throws UnsupportedTenancyException, IOException {
|
||||
SessionFactory sessionFactory = HibernateMultiTenantUtil.getSessionFactory();
|
||||
|
||||
SupplierDao myDb1Dao = new SupplierDao(sessionFactory, "mydb1");
|
||||
Supplier db1SupplierName = myDb1Dao.findByName("John");
|
||||
|
||||
// finding the same supplier name in another tenant
|
||||
// and we should not be able to find in there and both dbs are different.
|
||||
SupplierDao myDb2Dao = new SupplierDao(sessionFactory, "mydb2");
|
||||
Supplier db2SupplierName = myDb2Dao.findByName(db1SupplierName.getName());
|
||||
|
||||
assertNull(db2SupplierName);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.baeldung.hibernate.multitenancy;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity(name = "Car")
|
||||
@Table(name = "Car")
|
||||
public class Car implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1015320564683423342L;
|
||||
|
||||
private String brand;
|
||||
|
||||
@Id
|
||||
public String getBrand() {
|
||||
return brand;
|
||||
}
|
||||
|
||||
public void setBrand(String brand) {
|
||||
this.brand = brand;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package com.baeldung.hibernate.multitenancy;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.junit.Before;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import com.baeldung.hibernate.multitenancy.database.TenantIdNames;
|
||||
|
||||
public abstract class MultitenancyIntegrationTest {
|
||||
|
||||
public abstract String getPropertyFile();
|
||||
|
||||
@Mock
|
||||
private CurrentTenantIdentifierResolver currentTenantIdentifierResolver;
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
@Before
|
||||
public void setup() throws IOException {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
Mockito.when(currentTenantIdentifierResolver.validateExistingCurrentSessions())
|
||||
.thenReturn(false);
|
||||
|
||||
Properties properties = getHibernateProperties();
|
||||
properties.put(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
|
||||
|
||||
sessionFactory = buildSessionFactory(properties);
|
||||
|
||||
initTenant(TenantIdNames.MYDB1);
|
||||
initTenant(TenantIdNames.MYDB2);
|
||||
}
|
||||
|
||||
protected void initTenant(String tenantId) {
|
||||
whenCurrentTenantIs(tenantId);
|
||||
createCarTable();
|
||||
}
|
||||
|
||||
protected void whenCurrentTenantIs(String tenantId) {
|
||||
Mockito.when(currentTenantIdentifierResolver.resolveCurrentTenantIdentifier())
|
||||
.thenReturn(tenantId);
|
||||
}
|
||||
|
||||
protected void whenAddCar(String brand) {
|
||||
Session session = sessionFactory.openSession();
|
||||
Transaction tx = session.beginTransaction();
|
||||
Car car = new Car();
|
||||
car.setBrand(brand);
|
||||
session.save(car);
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
protected void thenCarFound(String brand) {
|
||||
Session session = sessionFactory.openSession();
|
||||
assertNotNull(session.get(Car.class, brand));
|
||||
}
|
||||
|
||||
protected void thenCarNotFound(String brand) {
|
||||
Session session = sessionFactory.openSession();
|
||||
assertNull(session.get(Car.class, brand));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void createCarTable() {
|
||||
Session session = sessionFactory.openSession();
|
||||
Transaction tx = session.beginTransaction();
|
||||
session.createSQLQuery("drop table Car if exists")
|
||||
.executeUpdate();
|
||||
session.createSQLQuery("create table Car (brand varchar(255) primary key)")
|
||||
.executeUpdate();
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
private Properties getHibernateProperties() throws IOException {
|
||||
Properties properties = new Properties();
|
||||
properties.load(getClass().getResourceAsStream(getPropertyFile()));
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static SessionFactory buildSessionFactory(Properties properties) {
|
||||
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(properties)
|
||||
.build();
|
||||
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
|
||||
metadataSources.addAnnotatedClass(Car.class);
|
||||
return metadataSources.buildMetadata()
|
||||
.buildSessionFactory();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.hibernate.multitenancy.database;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.hibernate.multitenancy.MultitenancyIntegrationTest;
|
||||
|
||||
public class DatabaseApproachMultitenancyIntegrationTest extends MultitenancyIntegrationTest {
|
||||
|
||||
@Override
|
||||
public String getPropertyFile() {
|
||||
return "/hibernate-database-multitenancy.properties";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDatabaseApproach_whenAddingEntries_thenOnlyAddedToConcreteDatabase() throws IOException {
|
||||
whenCurrentTenantIs(TenantIdNames.MYDB1);
|
||||
whenAddCar("myCar");
|
||||
thenCarFound("myCar");
|
||||
whenCurrentTenantIs(TenantIdNames.MYDB2);
|
||||
thenCarNotFound("myCar");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.baeldung.hibernate.multitenancy.database;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
||||
import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class MapMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider {
|
||||
|
||||
private final Map<String, ConnectionProvider> connectionProviderMap = new HashMap<>();
|
||||
|
||||
public MapMultiTenantConnectionProvider() throws IOException {
|
||||
initConnectionProviderForTenant(TenantIdNames.MYDB1);
|
||||
initConnectionProviderForTenant(TenantIdNames.MYDB2);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionProvider getAnyConnectionProvider() {
|
||||
return connectionProviderMap.values()
|
||||
.iterator()
|
||||
.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
|
||||
return connectionProviderMap.get(tenantIdentifier);
|
||||
}
|
||||
|
||||
private void initConnectionProviderForTenant(String tenantId) throws IOException {
|
||||
Properties properties = new Properties();
|
||||
properties.load(getClass().getResourceAsStream(String.format("/hibernate-database-%s.properties", tenantId)));
|
||||
DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl();
|
||||
connectionProvider.configure(properties);
|
||||
this.connectionProviderMap.put(tenantId, connectionProvider);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.baeldung.hibernate.multitenancy.database;
|
||||
|
||||
public class TenantIdNames {
|
||||
public static final String MYDB1 = "mydb1";
|
||||
public static final String MYDB2 = "mydb2";
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.baeldung.hibernate.multitenancy.schema;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.hibernate.multitenancy.MultitenancyIntegrationTest;
|
||||
import com.baeldung.hibernate.multitenancy.database.TenantIdNames;
|
||||
|
||||
public class SchemaApproachMultitenancyIntegrationTest extends MultitenancyIntegrationTest {
|
||||
|
||||
@Override
|
||||
public String getPropertyFile() {
|
||||
return "/hibernate-schema-multitenancy.properties";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSchemaApproach_whenAddingEntries_thenOnlyAddedToConcreteSchema() throws IOException {
|
||||
whenCurrentTenantIs(TenantIdNames.MYDB1);
|
||||
whenAddCar("Ferrari");
|
||||
thenCarFound("Ferrari");
|
||||
whenCurrentTenantIs(TenantIdNames.MYDB2);
|
||||
thenCarNotFound("Ferrari");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.baeldung.hibernate.multitenancy.schema;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
||||
import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.junit.Assert;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class SchemaMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider {
|
||||
|
||||
private final ConnectionProvider connectionProvider = initConnectionProvider();
|
||||
|
||||
@Override
|
||||
protected ConnectionProvider getAnyConnectionProvider() {
|
||||
return connectionProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
|
||||
return connectionProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection(String tenantIdentifier) throws SQLException {
|
||||
Connection connection = super.getConnection(tenantIdentifier);
|
||||
connection.createStatement()
|
||||
.execute(String.format("SET SCHEMA %s;", tenantIdentifier));
|
||||
return connection;
|
||||
}
|
||||
|
||||
private ConnectionProvider initConnectionProvider() {
|
||||
Properties properties = new Properties();
|
||||
try {
|
||||
properties.load(getClass().getResourceAsStream("/hibernate-schema-multitenancy.properties"));
|
||||
} catch (IOException e) {
|
||||
Assert.fail("Error loading resource. Cause: " + e.getMessage());
|
||||
}
|
||||
|
||||
DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl();
|
||||
connectionProvider.configure(properties);
|
||||
return connectionProvider;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.baeldung.hibernate.multitenancy.schema;
|
||||
|
||||
public class TenantIdNames {
|
||||
public static final String MYDB1 = "mydb1";
|
||||
public static final String MYDB2 = "mydb2";
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
hibernate.multiTenancy=DATABASE
|
||||
hibernate.multi_tenant_connection_provider=com.baeldung.hibernate.multitenancy.database.MapMultiTenantConnectionProvider
|
|
@ -0,0 +1,4 @@
|
|||
hibernate.connection.driver_class=org.h2.Driver
|
||||
hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1
|
||||
hibernate.connection.username=sa
|
||||
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
|
@ -0,0 +1,4 @@
|
|||
hibernate.connection.driver_class=org.h2.Driver
|
||||
hibernate.connection.url=jdbc:h2:mem:mydb2;DB_CLOSE_DELAY=-1
|
||||
hibernate.connection.username=sa
|
||||
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
|
@ -1,9 +0,0 @@
|
|||
hibernate.connection.driver_class=org.h2.Driver
|
||||
hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1
|
||||
hibernate.connection.username=sa
|
||||
hibernate.connection.autocommit=true
|
||||
jdbc.password=
|
||||
|
||||
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||
hibernate.show_sql=true
|
||||
hibernate.multiTenancy=DATABASE
|
|
@ -0,0 +1,7 @@
|
|||
hibernate.connection.driver_class=org.h2.Driver
|
||||
hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS MYDB1\\;CREATE SCHEMA IF NOT EXISTS MYDB2\\;
|
||||
hibernate.connection.username=sa
|
||||
hibernate.connection.autocommit=true
|
||||
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||
hibernate.multiTenancy=SCHEMA
|
||||
hibernate.multi_tenant_connection_provider=com.baeldung.hibernate.multitenancy.schema.SchemaMultiTenantConnectionProvider
|
Loading…
Reference in New Issue