J'ai une application Spring 3.2 qui utilise Hibernate 4 et Spring Transactions. Toutes les méthodes fonctionnaient très bien et je pouvais accéder correctement à la base de données pour enregistrer ou récupérer des entités. Ensuite, j'ai introduit du multithreading, et puisque chaque thread accédait à db, j'obtenais l'erreur suivante d'Hibernate:
org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
J'ai lu sur le Web que je dois ajouter <prop key="hibernate.current_session_context_class">thread</prop>
à ma configuration Hibernate, mais maintenant, chaque fois que j'essaie d'accéder à la base de données, j'obtiens:
org.hibernate.HibernateException: saveOrUpdate is not valid without active transaction
Cependant, mes méthodes de service sont annotées avec @Transactional
, et tout fonctionnait bien avant l'ajout de <prop key="hibernate.current_session_context_class">thread</prop>
.
Pourquoi il n'y a pas de transaction alors que les méthodes sont annotées avec @Transactional? Comment puis-je résoudre ce problème?
Voici ma configuration Hibernate (y compris la propriété de contexte de session):
<?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"/>
Lorsque vous utilisez des transactions gérées au printemps et au printemps , ne ne plaisante pas avec le hibernate.current_session_context_class
propriété [~ # ~] sauf si [~ # ~] vous utilisez JTA.
Spring définira par défaut sa propre implémentation CurrentSessionContext
(la SpringSessionContext ), mais si vous la définissez vous-même, ce ne sera pas le cas. Briser fondamentalement une bonne intégration des transactions.
La seule raison de modifier ce paramètre est chaque fois que vous souhaitez utiliser des transactions gérées par JTA, vous devez alors le configurer pour qu'il s'intègre correctement avec JTA.