I am working on migrating an application from Spring 3.2 to Spring 5. The application uses AWS RDS with a primary database as primary or master datasource and a replica database as read-only datasource. The application creates one session factory ( primarySessionFacotry) instance for the primary data source and another one ( readOnlySessionFactory) for the read-only data source so that the same DAO can be used for both datasource by wiring each session factories.
<bean id="primaryDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="jdbcUrl">
<value>${database.jdbcurl}</value>
</property>
<property name="user">
<value>${database.dbuser}</value>
</property>
<property name="password">
<value>${database.dbpassword}</value>
</property>
</bean>
<bean id="primarySessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="primaryDataSource"/>
<property name="mappingResources" ref="hbmFileLocations">
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">${hibernate.showSQL}</prop>
<prop key="hibernate.format_sql">${hibernate.formatSQL}</prop>
</props>
</property>
</bean>
<util:list id="hbmFileLocations" value-type="java.lang.String">
<value>com/xxxx/yyyyy/persistence/mappings/users.hbm.xml</value>
</util:list>
<bean id="primaryTransactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="primarySessionFactory">
</property>
</bean>
<tx:annotation-driven transaction-manager="primaryTransactionManager"/>
<bean id="readOnlyDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="jdbcUrl">
<value>${database.readonly.jdbcurl}</value>
</property>
<property name="user">
<value>${database.readonly.dbuser}</value>
</property>
<property name="password">
<value>${database.readonly.dbpassword}</value>
</property>
</bean>
<bean id="readOnlySessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="readOnlyDataSource"/>
<property name="mappingResources" ref="hbmFileLocations">
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">${hibernate.readonly.showSQL}</prop>
<prop key="hibernate.format_sql">${hibernate.readonly.formatSQL}</prop>
</props>
</property>
</bean>
<bean id="readOnlyTransactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="readOnlySessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="readOnlyTransactionManager"/>
DAOs are instantiated like this
<bean id="userDao" class="xxxxx.persistence.UserDao">
<property name="sessionFactory" ref="primarySessionFactory"/>
</bean>
<bean id="readOnlyUserDao" class="xxxxx.persistence.UserDao">
<property name="sessionFactory" ref="readOnlySessionFactory"/>
</bean>
This UserDao has a method like below
@Transactional
public List<User> getItems()
{
return sessionFactory.getCurrentSession().createQuery("from User user where isDeleted=false").list();
}
We are getting below exception when using the UserDao.getItems() method with readOnlyUserDao intance.
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:143)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:497)
Please note that the same code is perfectly working with Spring ( spring-orm and spring-tx 3.2)
Please assist to resolve this.