diff --git a/hibernate5/pom.xml b/hibernate5/pom.xml
new file mode 100644
index 0000000000..b7473ec5b7
--- /dev/null
+++ b/hibernate5/pom.xml
@@ -0,0 +1,62 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+ com.baeldung
+ hibernate5
+ 0.0.1-SNAPSHOT
+ hibernate5
+ http://maven.apache.org
+
+ UTF-8
+
+ 3.6.0
+
+
+
+ org.hibernate
+ hibernate-core
+ 5.2.9.Final
+
+
+ junit
+ junit
+ 4.12
+
+
+ com.h2database
+ h2
+ 1.4.194
+
+
+
+ hibernate5
+
+
+ src/main/resources
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ 1.8
+ 1.8
+
+
+
+
+
+
+
+
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/App.java b/hibernate5/src/main/java/com/baeldung/hibernate/App.java
new file mode 100644
index 0000000000..26a40bb782
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/App.java
@@ -0,0 +1,30 @@
+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();
+ }
+
+ }
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/ConfigurableMultiTenantConnectionProvider.java b/hibernate5/src/main/java/com/baeldung/hibernate/ConfigurableMultiTenantConnectionProvider.java
new file mode 100644
index 0000000000..b9ed2bd139
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/ConfigurableMultiTenantConnectionProvider.java
@@ -0,0 +1,41 @@
+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 connectionProviderMap =
+ new HashMap<>();
+
+
+ public ConfigurableMultiTenantConnectionProvider(
+ Map 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;
+ }
+
+}
\ No newline at end of file
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/HibernateMultiTenantUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateMultiTenantUtil.java
new file mode 100644
index 0000000000..c3e7b621d0
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateMultiTenantUtil.java
@@ -0,0 +1,95 @@
+package com.baeldung.hibernate;
+
+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 connectionProviderMap = new HashMap<>();
+ private static final String[] tenantDBNames = { "mydb1","mydb2"};
+
+ public static SessionFactory getSessionFactory() throws UnsupportedTenancyException {
+ if (sessionFactory == null) {
+ Configuration configuration = new Configuration().configure();
+ ServiceRegistry serviceRegistry = configureServiceRegistry(configuration);
+ sessionFactory = makeSessionFactory (serviceRegistry);
+// sessionFactory = configuration.buildSessionFactory(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(Configuration configuration) throws UnsupportedTenancyException {
+ Properties properties = configuration.getProperties();
+
+ connectionProviderMap = setUpConnectionProviders(properties, tenantDBNames);
+ properties.put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, new ConfigurableMultiTenantConnectionProvider(connectionProviderMap));
+
+ return new StandardServiceRegistryBuilder().applySettings(properties).build();
+ }
+
+ private static Map setUpConnectionProviders(Properties properties, String[] tenantNames) throws UnsupportedTenancyException {
+ Map 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";
+
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java
new file mode 100644
index 0000000000..c1f7301d46
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java
@@ -0,0 +1,24 @@
+package com.baeldung.hibernate;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+
+public class HibernateUtil {
+
+ private static final SessionFactory sessionFactory;
+
+ static {
+ try {
+ Configuration configuration = new Configuration().configure();
+ sessionFactory = configuration.buildSessionFactory();
+
+ } catch (Throwable ex) {
+ System.err.println("Initial SessionFactory creation failed." + ex);
+ throw new ExceptionInInitializerError(ex);
+ }
+ }
+
+ public static SessionFactory getSessionFactory() {
+ return sessionFactory;
+ }
+}
\ No newline at end of file
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/UnsupportedTenancyException.java b/hibernate5/src/main/java/com/baeldung/hibernate/UnsupportedTenancyException.java
new file mode 100644
index 0000000000..99d9505ea3
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/UnsupportedTenancyException.java
@@ -0,0 +1,8 @@
+package com.baeldung.hibernate;
+
+public class UnsupportedTenancyException extends Exception {
+ public UnsupportedTenancyException (String message) {
+ super(message);
+ }
+
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Supplier.java b/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Supplier.java
new file mode 100644
index 0000000000..d0187bba47
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Supplier.java
@@ -0,0 +1,67 @@
+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());
+ }
+}
diff --git a/hibernate5/src/main/java/hibernate.cfg.xml b/hibernate5/src/main/java/hibernate.cfg.xml
new file mode 100644
index 0000000000..26be05f931
--- /dev/null
+++ b/hibernate5/src/main/java/hibernate.cfg.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ org.h2.Driver
+ jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1
+ sa
+
+ org.hibernate.dialect.H2Dialect
+ DATABASE
+
+
diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/MultiTenantHibernateTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/MultiTenantHibernateTest.java
new file mode 100644
index 0000000000..4a701de48d
--- /dev/null
+++ b/hibernate5/src/test/java/com/baeldung/hibernate/MultiTenantHibernateTest.java
@@ -0,0 +1,73 @@
+package com.baeldung.hibernate;
+import static org.junit.Assert.assertNotEquals;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.baeldung.hibernate.pojo.Supplier;
+
+
+public class MultiTenantHibernateTest {
+ @Test
+ public void givenDBMode_whenFetchingSuppliers_thenComparingFromDbs () {
+ SessionFactory sessionFactory;
+ try {
+ sessionFactory = HibernateMultiTenantUtil.getSessionFactory();
+
+ Session db1Session = sessionFactory
+ .withOptions().tenantIdentifier("mydb1").openSession();
+
+ initDb1(db1Session);
+
+ Transaction transaction = db1Session.getTransaction();
+ transaction.begin();
+ Supplier supplierFromDB1 = (Supplier)db1Session.createCriteria(Supplier.class).list().get(0);
+ transaction.commit();
+
+ Session db2Session = sessionFactory
+ .withOptions().tenantIdentifier("mydb2").openSession();
+
+ initDb2(db2Session);
+ db2Session.getTransaction().begin();
+ Supplier supplierFromDB2 = (Supplier) db2Session.createCriteria(Supplier.class).list().get(0);
+ db2Session.getTransaction().commit();
+
+ System.out.println(supplierFromDB1);
+ System.out.println(supplierFromDB2);
+
+ assertNotEquals(supplierFromDB1, supplierFromDB2);
+ } catch (UnsupportedTenancyException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+
+ private void initDb1(Session db1Session) {
+ System.out.println("Init DB1");
+ Transaction transaction = db1Session.getTransaction();
+ transaction.begin();
+ db1Session.createSQLQuery("DROP ALL OBJECTS").executeUpdate();
+ db1Session.createSQLQuery("create table Supplier (id integer generated by default as identity, country varchar(255), name varchar(255), primary key (id))").executeUpdate();
+ db1Session.createSQLQuery("insert into Supplier (id, country, name) values (null, 'John', 'USA')").executeUpdate();
+ transaction.commit();
+ }
+
+ private void initDb2(Session db2Session) {
+ System.out.println("Init DB2");
+ Transaction transaction = db2Session.getTransaction();
+ transaction.begin();
+ db2Session.createSQLQuery("DROP ALL OBJECTS").executeUpdate();
+ db2Session.createSQLQuery("create table Supplier (id integer generated by default as identity, country varchar(255), name varchar(255), primary key (id))").executeUpdate();
+ db2Session.createSQLQuery("insert into Supplier (id, country, name) values (null, 'Miller', 'UK')").executeUpdate();
+ transaction.commit();
+ }
+}
diff --git a/pom.xml b/pom.xml
index a705ac7cb1..7671d05d75 100644
--- a/pom.xml
+++ b/pom.xml
@@ -226,7 +226,7 @@
1.6.0
maven
-
+ hibernate5
@@ -253,4 +253,4 @@
-->
-
+
\ No newline at end of file