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:
committed by
KevinGilmore
parent
13d47f0873
commit
85f12cd254
@@ -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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user