All
I was evaluating Multi-Tenancy feature present in Hibernate 4(4.1.0) along with Spring 3(3.1.0), but was not able to get it working with HibernateTransaction setting. I have defined settings as follows.
LocalSessionFactoryBean :
@org.springframework.context.annotation.Configuration
public class Configuration {
@Inject private DataSource dataSource;
@Inject private MultiTenantConnectionProvider multiTenantConnectionProvider;
@Bean
public LocalSessionFactoryBean sessionFactory() throws IOException{
LocalSessionFactoryBean bean = new LocalSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setPackagesToScan("com");
bean.getHibernateProperties().put("hibernate.multi_tenant_connection_provider", multiTenantConnectionProvider);
bean.getHibernateProperties().put("hibernate.multiTenancy", "SCHEMA");
bean.getHibernateProperties().put("hibernate.tenant_identifier_resolver", new CurrentTenantIdentifierResolverImpl());
bean.setConfigLocation(new ClassPathResource("/hibernate.cfg.xml"));
return bean;
}
}
Configuration.xml :
<context:component-scan base-package="com.green" />
<context:annotation-config />
<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Declare a datasource that has pooling capabilities -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close" p:driverClass="${app.jdbc.driverClassName}"
p:jdbcUrl="${app.jdbc.url}" p:user="${app.jdbc.username}" p:password="${app.jdbc.password}"
p:acquireIncrement="5" p:idleConnectionTestPeriod="60" p:maxPoolSize="100"
p:maxStatements="50" p:minPoolSize="10" />
<!-- Declare a transaction manager -->
<bean id="transactionManager"
class="com.green.saas.hibernate.SaasHibernateTransactionManager"
depends-on="sessionFactory" >
<property name="sessionFactory" ref="sessionFactory"></property>
<property name="dataSource" ref="dataSource"></property>
</bean>
If I use plain HibernateTransactionManager provided by spring 3 I get error tenant identifier not set, reason for this being, it opens a session as follows
Session newSession = SessionFactoryUtils.openSession(getSessionFactory( ));
(Session) ReflectionUtils.invokeMethod(openSessionMethod, sessionFactory)
in openSession
methodMethod openSessionMethod = ClassUtils.getMethod(SessionFactory.class, "openSession")
above openSessionMethod
argument is defined as.we can see that there is no hook where you can provide tenant-identifier as expected while opening a session with tenant-identifier e.g
Session newSession = getSessionFactory().withOptions().tenantIdentifier ( "abc" ).openSession();
or
class instance provided by hibernate property "hibernate.tenant_identifier_resolver" is called by which session is provided with tenant identifier.
To overcome this I extended class HibernateTransactionManager and override method doBegin and where new session is opened I opened it
getSessionFactory().withOptions().tenantIdentifier ( "abc" ).openSession();
this makes thing click and work.
I just wanted to know, is this above approach fine or there is some setting that I am not aware of that makes it work out of the box.
Thanks in advance.
Hibernate - 4.1.0 Spring - 3.1.0
Multitenancy allows multiple clients or tenants use a single resource or, in the context of this article, a single database instance. The purpose is to isolate the information each tenant needs from the shared database. In this tutorial, we'll introduce various approaches to configuring multitenancy in Hibernate 5.
Multi-tenancy refers to an architecture in which a single instance of a software application serves multiple tenants or customers. It enables the required degree of isolation between tenants so that the data and resources used by tenants are separated from the others.
In a multitenancy environment, multiple customers share the same application, in the same operating environment, on the same hardware, with the same storage mechanism. In virtualization, every application runs on a separate virtual machine with its own OS.
It looks like this feature was buggy on Hibernate
side with the version you used: SPR-9222, HHH-7306.
Starting from Hibernate
version 4.1.4
You should use CurrentTenantIdentifierResolver
to pass the current tenant ID to SessionFactory
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With