views:

800

answers:

1

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.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.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;
                    }
});
+2  A: 

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.

Adeel Ansari
thanks Vinegar,but i havent used getHibernateTemplate().getSessionFactory().openSession() in my DAOs,I have only used like:return (Long) this.getHibernateTemplate().save(family);andreturn (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; }});
umanga
I suppose using hibernateTemplate to execute or save, tend to open a new session to perform the things. For example, `getHibernateTemplate().save(family)`, will use Session.save() somewhere down the road, and most likely will open a new session. What say you?
Adeel Ansari