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"/>
Hibernate deals with database specific transactions, whereas spring provides a general transaction management service. @Transactional is a nice way of configuring transaction management behaviour.
hibernate. context. CurrentSessionContext ) and a new configuration parameter ( hibernate. current_session_context_class ) have been added to allow pluggability of the scope and context of defining current sessions.
Obviously, you can. A hibernate session is more or less a database connection and a cache for database objects. And you can have multiple successive transactions in a single database connection. More, when you use a connection pool, the connection is not closed but is recycled.
@Transactional helps you to extend scope of Session . Session is open first time when getCurrentSession() is executed and it is closed when transaction ends and it is flushed before transaction commits.
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.
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