Reputation: 3171
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
Upvotes: 11
Views: 8908
Reputation: 6811
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
.
Upvotes: 5