-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: Modification of an element of a collection
PostPosted: Sun Sep 27, 2009 2:40 am 
Newbie

Joined: Sun Jul 27, 2008 4:23 am
Posts: 10
I'm building a web app with Stripes/Spring/Hibernate. Basic CRUD-type app. On one page, there's a list of volumes loaded with code from the class VolumesActionBean, and the user can click on one to edit it, which will then open an edit page where the individual volume is again requested by code in VolumeTypeConverter (it's a Stripes idiom). On save, the volume is requested again from VolumeTypeConverter then saved by code in VolumeActionBean.

The problem is that once the change is made, any attempt to save results in
Code:
org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions


I've extracted the problem down into a unit test that throws the exception:
Code:
package com.dahosek.catalog.book.dao;

import java.util.List;

import org.junit.*;

import com.dahosek.catalog.book.Volume;
import org.hibernate.*;
import org.hibernate.cfg.*;

public class VolumeHibernateDaoTest {
   @Test
   public void canLoadAndSave() {
      VolumeHibernateDao dao = new VolumeHibernateDao();
      
      SessionFactory sessionFactory = new AnnotationConfiguration()
         .configure()
         .buildSessionFactory();
      dao.setSessionFactory(sessionFactory);

      List<Volume> volumes = dao.findAll();
      Long id = volumes.get(0).getId();
      Volume volume = dao.findById(id, true); //(3)
      volume.setCallNumber("New Call Number"); //(1)
      dao.makePersistent(volume); //(2)
      Volume vol2 = dao.findById(id, false);
      Assert.assertEquals("New Call Number", vol2.getCallNumber());
   }
}

Removing the line at (1) removes the exception thrown at (2). The question is, given the structure of the application, I can't avoid the request to generate a new object at (3). How do I get the application to work without the exception being thrown?

(My Dao class is a slightly modified version of the Dao class from the Bauer/King book).


Top
 Profile  
 
 Post subject: Re: Modification of an element of a collection
PostPosted: Sun Sep 27, 2009 6:49 am 
Senior
Senior

Joined: Mon Jul 07, 2008 4:35 pm
Posts: 141
Location: Berlin
Hi dhosek,

are you sure that you properly detach your volume from the session? Does your DAO method findById() close its session at the end?
Code:
Volume volume = dao.findById(id, true); //(3)


Otherwise, please post the corresponding DAO code.

CU
Froestel

_________________
Have you tried turning it off and on again? [Roy]


Top
 Profile  
 
 Post subject: Re: Modification of an element of a collection
PostPosted: Sun Sep 27, 2009 11:26 pm 
Newbie

Joined: Sun Jul 27, 2008 4:23 am
Posts: 10
Here's my DAO
Code:
public class GenericHibernateDao<T, ID extends Serializable> extends HibernateDaoSupport implements GenericDao<T, ID> {

   private Class<T> persistentClass;
   
   @SuppressWarnings("unchecked")
   public GenericHibernateDao() {
      this.persistentClass = (Class<T>) ( (ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
   }
   
   public Class<T> getPersistentClass() {
      return persistentClass;
   }
   
   @Override
   public void clear() {
      getSession().clear();
   }

   @Override
   public List<T> findAll() {
      return findByCriteria();
   }

   @SuppressWarnings("unchecked")
   @Override
   public List<T> findByExample(T exampleInstance, String... excludeProperty) {
      Criteria criteria = getSession().createCriteria(getPersistentClass());
      Example example = Example.create(exampleInstance);
      for (String exclude : excludeProperty) {
         example.excludeProperty(exclude);
      }
      criteria.add(example);
      return criteria.list();
   }

   @SuppressWarnings("unchecked")
   @Override
   public T findById(ID id, boolean lock) {
      T entity;
      if (lock) {
         entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE);
      }
      else {
         entity = (T) getSession().load(getPersistentClass(), id);
      }
      return entity;
   }

   @Override
   public void flush() {
      getSession().flush();
   }

   @Override
   public T makePersistent(T entity) {
      getSession().saveOrUpdate(entity);
      return entity;
   }

   @Override
   public void makeTransient(T entity) {
      getSession().delete(entity);
   }

   @SuppressWarnings("unchecked")
   protected List<T> findByCriteria(Criterion... criterion) {
      Criteria criteria = getSession().createCriteria(getPersistentClass());
      for (Criterion c: criterion) {
         criteria.add(c);
      }
      return criteria.list();
   }
}

This is very close to the code from Chapter 16, with the exception of using the getSession from HibernateDaoSupport rather than getting one from HibernateUtil.getSessionFactory().getCurrentSession() (which is then reused in all dao calls).

I did determine that I can reduce the code necessary to spark the error with a much simpler set of code. Apparently it's enough to modify the object before a saveorpersist (thanks Froestel for spotting that).

Update: It looks like I shouldn't be using getSession(), I'll dig deeper and report back unless someone can point me at a fix first...


Top
 Profile  
 
 Post subject: Re: Modification of an element of a collection
PostPosted: Mon Sep 28, 2009 2:00 pm 
Senior
Senior

Joined: Mon Jul 07, 2008 4:35 pm
Posts: 141
Location: Berlin
Hi dhosek,

if your using HibernateDaoSupport you apparently use the Spring Framework. I'm not sure how sessions are handled there exactly (check Spring's docs on that). You should probably check for Transaction Handling, too. Depending on your configuration it might be necessary to explicitly do transaction handling in your code. So check your Hibernate config (or Spring/Hibernate config).

CU
Froestel

_________________
Have you tried turning it off and on again? [Roy]


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.