Spring-Hibernate : Illégal de tenter d'associer une collection avec deux sessions ouvertes
Je suis en train de mettre à jour l'enregistrement dans des bases de données MySql. pendant la mise à jour il jeta exception suivante
org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:410)
at org.hibernate.event.def.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:43)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:123)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:293)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
at com.tcs.ignite.ih.spring.dao.UserDAOImpl.saveUpdateUserbean(UserDAOImpl.java:185)
at com.tcs.ignite.ih.spring.dao.UserDAOImpl.blockuser(UserDAOImpl.java:204)
at com.tcs.ignite.ih.spring.service.UserServiceImpl.blockUser(UserServiceImpl.java:187)
at com.tcs.ignite.ih.spring.controller.AdminHomeController.BlockUser(AdminHomeController.java:48)
- Je vérifier pour la session. Sa ferme dans le bloc finally de chaque methode . Pas en mesure de comprendre ce qui est mal. Je suis capable de insertupdate opertion avec d'autres méthodes sans aucun problème, mais seulement saveUpdateUserBean méthode lance une exception
UserDAOImpl:
import com.tcs.ignite.ih.hibernate.model.Userdetails;
import com.tcs.ignite.ih.hibernate.model.Userlog;
import com.tcs.ignite.ih.hibernate.model.Userrole;
import com.tcs.ignite.ih.spring.bean.LoginBean;
import com.tcs.ignite.ih.spring.util.LogFile;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Repository
@Transactional
public class UserDAOImpl implements UserDAO {
@Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public Userdetails getUserDetails(String username) {
Session session = getSessionFactory().openSession();
Userdetails u = null;
try {
u = (Userdetails) getSessionFactory().openSession()
.createCriteria(Userdetails.class)
.add(Restrictions.eq("email", username)).uniqueResult();
} catch (Exception e) {
LogFile.log.error("UserDAO getuserDetails(): " + e.toString());
} finally {
if (session.isOpen()) {
session.close();
}
return u;
}
}
@Override
public boolean saveUpdateUserbean(Userdetails u) {
Session session = getSessionFactory().openSession();
Transaction tr = session.beginTransaction();
boolean y = false;
try {
session.saveOrUpdate(u);
tr.commit();
y = true;
} catch (Exception e) {
tr.rollback();
e.printStackTrace();
} finally {
if (session.isOpen()) {
session.close();
}
return y;
}
}
@Override
public boolean blockuser(String email) {
Userdetails u = this.getUserDetails(email);
return this.saveUpdateUserbean(u);
}
}
ServiceImpl:
import com.tcs.ignite.ih.hibernate.model.Userdetails;
import com.tcs.ignite.ih.hibernate.model.Userlog;
import com.tcs.ignite.ih.spring.bean.LogBean;
import com.tcs.ignite.ih.spring.bean.RegisterBean;
import com.tcs.ignite.ih.spring.bean.UserBean;
import com.tcs.ignite.ih.spring.bean.loadUserBean;
import com.tcs.ignite.ih.spring.dao.UserDAO;
import com.tcs.ignite.ih.spring.util.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserDAO dao;
@Override
public boolean blockUser(String email) {
return dao.blockuser(email);
}
}
applicationContext.xml:
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:jdbc.properties" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>
<!-- ADD PERSISTENCE SUPPORT HERE (jpa, hibernate, etc) -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.tcs.ignite.ih.hibernate.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven />
</beans>
Je suis en mesure d'effectuer toute opération de base de données en utilisant la même configuration mais quand je fais appel blockuser() la méthode de serviceImpl son appel DAO méthodes et les saveupdateUserBean est en train de jeter exception ci-dessus? m-je raté quelque chose?
OriginalL'auteur Dramorian | 2014-04-16
Vous devez vous connecter pour publier un commentaire.
Hibernate manuel dit:
Il a aidé dans mon cas.
DAO:
POJO Annonces (Un Utilisateur a de nombreuses annonces):
OriginalL'auteur D.Zhur.
Appel à la session de l'outil:
Ne pas ouvrir et fermer manuellement vous-même.
La collection est d'essayer d'être associé à deux séances. Aussi
SessionFactory
, bien que parfaitement valide, ne fait pas partie de la JPA. JPA s'appuie surEntityFactory
.Vos méthodes, parce que vous définir la classe à la transaction, ne nécessitent pas de manuellement démarrage d'une transaction. Supprimer ce (et toute référence à des transactions) à partir de
saveorUpdate
.Les Transactions conventionnellement aller sur la couche de service, pas de dépôts. De sorte que vous pouvez emballer plusieurs référentiel/DAO appels en une seule couche de service de la méthode transactionnelle.
hum ouais, je l'ai eu en avance de me voir mettre à jour. Vous définissez la classe de la transaction à l'aide d'une annotation - pas besoin d'ouvrir une transaction dans le code.
j'ai d'autres méthodes aussi dans le même daoImpl. dois-je supprimer toutes les transactions à partir de ces méthodes? et comment puis-je commettre saveupdate sans opération?
ou supprimer l'annotation ... avoir une seule transaction, c'est l'erreur. Il y a differetn types de transactions à des annotations. Nécessitent de nouvelles, en lecture seule, etc. J'ai l'habitude de le définir sur chaque méthode en tant que de besoin.
j'ai essayé sans @Transactional annotation. mais tout de même exception est là.
OriginalL'auteur NimChimpsky
Le problème était dû à une mauvaise utilisation de la mettre à jour en cascade dans l'un des mappages. Voici un exemple de mappage de champ:
Retrait de la cascade = CascadeType.Fixe le problème.
Conclusion: utilisez soigneusement mises à jour en cascade comme il peut vous causer des ennuis. L'utiliser lors de la logique métier l'exige. Dans l'exemple ci-dessous il n'y avait pas besoin d'elle, de sorte que la suppression il était à la fois d'affaires et en programmant une bonne décision.
Source: http://blog.tremend.ro/2007/03/05/illegal-attempt-to-associate-a-collection-with-two-open-sessions/
Merci homme, cela fonctionne.
OriginalL'auteur Lazy Coder
problème si u utilisez code ci-dessous
au lieu d'utiliser
getSession()
si vous utilisez la"getHibernateTemplate().getSessionFactory().openSession()
, à l'origine de deux sessions d'être ouvert à la sametime.OriginalL'auteur Naveen
J'ai eu le même problème que vous et je n'ai trouvé aucune solution à mon Problème spécifique. J'ai dû fermer la Session sur la collection manuellement avec:
Je suppose que ce n'est pas une bonne Pratique pour résoudre la question comme cela, mais pour moi, c'était le seul moyen.
EDIT: bien sûr, cela ne fonctionne que sur un Jeu pas si la Collection est une Liste ou qqch. d'autre...
OriginalL'auteur Diana