I have a Spring 3.2 application that uses Hibernate 4 and Spring Transactions. All the methods were working great and I could access correctly the database to save or retrieve entities. Then, I introduced some multithreading, and since each thread was accessing to db I was getting the following error from Hibernate:
org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
I read from the web that I've to add <prop key="hibernate.current_session_context_class">thread</prop>
to my Hibernate configuration, but now every time I try to access the db I get:
org.hibernate.HibernateException: saveOrUpdate is not valid without active transaction
However my service methods are annotated with @Transactional
, and all was working fine before the add of <prop key="hibernate.current_session_context_class">thread</prop>
.
Why there is no transaction although the methods are annotated with @Transactional? How can I solve this problem?
Here is my Hibernate configuration (including the session context property):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- Hibernate session factory -->
<bean
id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="dataSource" >
<ref bean="dataSource" />
</property>
<property name="hibernateProperties" >
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
<property name="annotatedClasses" >
<list>
...
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
When using spring and spring managed transactions never mess around with the hibernate.current_session_context_class
property UNLESS you are using JTA.
Spring will by default set its own CurrentSessionContext
implementation (the SpringSessionContext), however if you set it yourself this will not be the case. Basically breaking proper transaction integration.
The only reason for changing this setting is whenever you want to use JTA managed transactions, then you have to setup this to properly integrate with JTA.