org.hibernate.nonuniqueobjectexception
In this section, you will learn about the exception org.hibernate.nonuniqueobjectexception and its cause.
In Hibernate, a session can not hold two duplicate Persistence Object , means (in a session) two persistence object of same class can not represent the same row. It also assures that two detached object can not represent the same row.
What is detached object ?
A new persistence class instance, which is not related to a Session and has not contained any value representing row of a database table and also have not contained any identifier value, is considered as transient by Hibernate.
Student student=new Student(); student.setName("Rajesh"); // student is in transient state
While a persistence instance , represents a row / rows in the database table and contains an identifier value. Also it is associated with Session.
Long id = (Long) session.save(student); // person is now in a persistent state
You can convert transient instance into persistence by associating it with a Session.
Now after closing the Hibernate Session, the persistent instance will become a detached instance or object.
session.close(); //student is now become detached object or instance
CAUSE / REASON
As stated above, a session in Hibernate can not hold two duplicate Persistence Object , means (in a session) two persistence object of same class can not represent the same row. It also assures that two detached object can not represent the same row.
Consider the below code :
Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Student s1 = (Student)session.get(Student .class, 1); transaction.commit(); session.close(); //s1 is now detached instance. session = sessionFactory.openSession(); transaction = session.beginTransaction(); Student s2 = (Student )session.get(Student .class, 1); //As you can see above, s2 represents the same persistent row as s1. //When we try to reattach s1, an exception is thrown session.update(s1); transaction.commit(); session.close();
When you try to execute the above code which attempt to reattach s1 , the following exception occurs :
Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.intertech.domain.Student#1] at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness (StatefulPersistenceContext.java:699)
The merge( ) method is used to deal with situation. After executing below code :
Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Student s1 = (Student )session.get(Student .class, 1); transaction.commit(); session.close(); //s1 is now detached. session = sessionFactory.openSession(); transaction = session.beginTransaction(); Student s2 = (Student )session.get(Student .class, 1); Student s3 = (Student ) session.merge(s1); if (s2 == s3) { System.out.println("s2 and s3 are equal"); } transaction.commit(); session.close();
you will get the following output :
s2 and s3 are equal
Means if we use merge( ) method, Hibernate will first check whether
a Persistent instance of that type already exists in the persistent
context. It uses the object identifiers to check on this existence. If another
instance exists, it copies the state
of the Detached object (s1 above) into the existing Persistence object (s2
above). If no other instance exists,
Hibernate just reattaches the Detached object.