In the standalone application(single threaded command line tool) I am developing ,I use Spring +Hibernate. It has DAO and Service layers and for DAOs I use HibernateDAOSupport. The collections in domain model are lazy-loading.
Since for lazy-loading I need to keep the Session opended,I open session at start of my application using:
HibernateTemplate tmpl;
SessionFactoryUtils.initDeferredClose(tmpl.getSessionFactory());
//do file reads,parse CSV , persist objects (normally takes along time)
//
//Finally
SessionFactoryUtils.processDeferredClose(tmpl.getSessionFactory());
But during execution ,I get the error:
Exception in thread "main" org.springframework.orm.hibernate3.HibernateSystemException: Illegal attempt to associate a collection with two open sessions; nested exception is org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions Caused by: 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.e开发者_如何学运维vent.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.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:33) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70) at org.hibernate.impl.SessionImpl.fireUpdate(SessionImpl.java:564) at org.hibernate.impl.SessionImpl.update(SessionImpl.java:552)
How to fix this?
at org.hibernate.impl.SessionImpl.update(SessionImpl.java:544) at org.springframework.orm.hibernate3.HibernateTemplate$14.doInHibernate(HibernateTemplate.java:657) at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:372) at org.springframework.orm.hibernate3.HibernateTemplate.update(HibernateTemplate.java:654) at org.springframework.orm.hibernate3.HibernateTemplate.update(HibernateTemplate.java:650) at com.bigg.nihonbare.common.dao.hibernate.CommonDAOImpl.updateFamily(CommonDAOImpl.java:40) at com.bigg.nihonbare.common.service.impl.CommonServiceImpl.updateFamily(CommonServiceImpl.java:55) at com.bigg.nihonbare.util.flow.DynaRowHibernateUpdateHandler.handleRow(DynaRowHibernateUpdateHandler.java:72)
NOTE : In my DAOs I only have used methods like;
return (Long) this.getHibernateTemplate().save(family);
return (Family) this.getHibernateTemplate().execute(
new HibernateCallback() {
public Object doInHibernate(Session session) {
Criteria criteria = session
.createCriteria(Family.class);
criteria.add(Expression.eq("familyId", familyId));
if (criteria.list().size() > 0) {
return criteria.list().get(0);
}
return null;
}
});
Watch for getHibernateTemplate().getSessionFactory().openSession()
in your DAO, you might be ending up opening 2 sessions, since you lately switched to this architecture, I know it from your other previous question.
Hint: Use getSession()
instead. This SpringSource Forum's thread might be helpful.
There are a lot of session associated to each thread separately .session is not a Shared variables but sessionfactory is,session is created by spring container if you inject sessionfactory into DAO.
精彩评论