Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate: different object with the same identifier value was already associated with the session [duplicate]

Possible Duplicate:
Hibernate Error: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session

when I use the DAO.update(userbean), session.SaveOrUpdate(e);throw the Exception:different object with the same identifier value was already associated with the session

the function is like next:

    public E save(E e) {
    Session session = null;
    try {
        session = sessionFactory.openSession();
        log.debug("session="+session.hashCode()+" save "+e);
        session.SaveOrUpdate(e);  //here throws exception 
        session.flush();
    }
    catch (Exception e1) {
        log.err("Cannot open hibernate session "+ e1.getMessage()+" cause : "+e1.getCause());
        e1.printStackTrace();
    }
    finally { if ( session != null ) session.close(); session = null;}
    return e ;
}

the userbean is an instance of class UserBean

public class UserBean{
   private List<GroupBean> groups = new ArrayList<GroupBean> ();
   private List<RoleBean> roles = new ArrayList<RoleBean> ();
}

public class GroupBean{
private List<RoleBean> roles = new ArrayList<RoleBean> ();
}

every groupbean has a list of roles, which are not changed.

in database, group and role is many-to-many mapping,

for example,

we have a groupbean#1, it's roles: rolebean#1, rolebean#2;

groupbean#2, which roles are rolebean#1.

now I create a new userbean#1, it's groups is groupbean#1 and if I want to add the rolebean#1 to userbean#1, it will throws the exception like the title descript

I look the server.log, and find that when I user DAO.save, the saveOrUpdate order is:

userbean#1
|---|-----------***userbean.groups
|     |     groupbean#1
|     |         groupbean.roles
|     |             rolebean#1  # save relebean#1 the first time
|     |             ---done rolebean#1
|     |         ------done all rolebeans of group.roles
|     |     ---done groupbean#1
|     |-----------done all groupbeans of userbean.groups
|---|-----------***userbean.roles
     |      rolebean#1          # save rolebean#1 the second time, and throws exception here!
     |      ----done rolebean#1
     |      .....
     |-----------done all rolebeans of userbean.roles

the cause of the exception is rolebean#1 has been saved twice in a session, and their identity is the same.

In the function save(E e), If I use

session.merge(e);

replace

session.SaveOrUpdate(e);

will not throw exception, but the rolebean#1 is not assocaited to userbean#1

anyone can give some suggestions about this?

like image 989
user421851 Avatar asked Aug 24 '10 02:08

user421851


People also ask

How to handle exceptions in Hibernate?

Hibernate provides better handle than the JDBCException . Developers can use the try and catch block to handle the exceptions. Put the line of code that may cause an exception in a try block and according to that exception put the exception handler in the catch block.

What is difference between Merge and update in hibernate?

Hibernate handles persisting any changes to objects in the session when the session is flushed. update can fail if an instance of the object is already in the session. Merge should be used in that case. It merges the changes of the detached object with an object in the session, if it exists.

When exception happens in Hibernate?

Many conditions can cause exceptions to be thrown while using Hibernate. These can be mapping errors, infrastructure problems, SQL errors, data integrity violations, session problems, and transaction errors. These exceptions mostly extend from HibernateException.


1 Answers

It would be easier to identify the exact cause if we can see the code where you're assigning the role bean to both the user and then the group.

In general, what the exception tells us is that there are two versions of that role bean (two instances). The first one gets updated, then Hibernate hits the second one, and recognizes it's the same identifier but a different detached version of the role.

Hibernate's not sure which is correct, and under saveOrUpdate, it throws an exception to let you know.

Merge's contract works differently, in that it will assume you meant to save it again (i.e., merge all my changes), and thus will reattach the second version, merge all changes, and save any updates.

I've blogged about SaveOrUpdate vs Merge with some more detail to explain what's going on.

If you want to stick with SaveOrUpdate, you're going to need to figure out what you're doing in the assignment that's causing a different instance of the role to be assigned to the user's role collection versus to the groups.

Otherwise, if the effects of merge work for you (which is in line with the JPA standard), then use it.

like image 175
Stevi Deter Avatar answered Oct 16 '22 13:10

Stevi Deter