3

My class Foo has method:

 protected void saveMany(Collection<T> many) {  
    for(Object one : many) {
            one = session.merge(one); // also tried this commented out
            session.saveOrUpdate(one); // session.merge(one);   
        }

Tried to use saveOrUpdate and also merge, but both gave me this exception:

Error: Invocation of method 'saveMany' in class Foo threw exception class org.hibernate.HibernateException : org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [Bar#581301]

How to fix this?

Side note:

When I truncate my table, the saving part works, but when I have the table populated, and run this method again, thus updating the table, it fails, with this exception

10
  • When you called merge() did you remember to call saveOrUpdate() afterwards on the instance returned from merge() and not the instance you passed into merge() as a parameter? See my answer here Commented Aug 13, 2012 at 13:24
  • @Brad : no I didnt call saveOrUpdate at all, I just called merge. You mean something like this? session.saveOrUpdate(session.merge(one)), it says : The left-hand side of an assignment must be a variable Commented Aug 13, 2012 at 13:33
  • @Brad : I did this : one = session.merge(one); session.saveOrUpdate(one); Commented Aug 13, 2012 at 13:39
  • stackoverflow.com/questions/1074081/… Commented Aug 13, 2012 at 13:48
  • @invariant Okay I think I found where this happens, but how can I get the first instance of the object out of hibernate context? Commented Aug 13, 2012 at 14:02

4 Answers 4

6

If you have a detached instance of a Class with @Id that already exists in the Hibernate Session cache, then you will have to call merge() to merge the detached instance into the cache. Then you should call saveOrUpdate().

But you have to be careful to persist the instance returned from the call to merge() and not the instance you passed in as a parameter. So you code has to look like this

mergedOne = session.merge(one);
session.saveOrUpdate(mergedOne);

If you're operating inside a transaction the database will not be updated until the session ends and the transaction commits, or you explicitly call flush()

Sign up to request clarification or add additional context in comments.

Comments

1

It says that you are trying to save a new object with an Id already used by another one.

Probably, you do not have properly implemented equals and hashCode. So, hibernate finds that you want to save Object2 with id1, and in the database there is Object2 with id1, but not Object2.equals(Object1)

9 Comments

Maybe, but thats what I want to do: When there is object with same primary key in database, just overwrite the fields.
But does your object implement equals()? Even if it is just an equals of the id. In a course about JPA (ok, not Hibernate) I was told that you must properly implement equals for it to work.
No it doesnt, can you give me a link about what you mean? I don't have equals nowhere.
Wow, this is really confusing and I don't really understand, why I must make another identifier, when I got primary key.
|
0

You are probably trying to Save List<T> which has one or more equals objects.

Use SaveOrUpdate or merge to solve it or simpply try to make all objects unique.

3 Comments

No I don't have List, I have object T. I tried using merge and saveOrUpdate as seen in initial post.
You are passing Collection<T> and List extends Collection<T> so your Collection has duplicates. Try to remove those duplicates.
Could it be the problem that my actual method has 2 collections for arguments like this : saveMany(Collection<T> update, Collection<T> delete) . I removed one from initial code to simplify things.
0

You have multiple versions of "one" in the cache of your Hibernatesessions!

You must must find the instances of "one" and remove the cache-information from the Hibernatesessions using ".evict(...)".

Finally you can call saveOrUpdate succesuflly!

2 Comments

I think I am doing this, but I close my last session.
close != evict. The reference between the "one" and the closed-session is still given! What sais the System.out.println(one.getClass()) ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.