You get a NonUniqueObjectException
if you try to reattach a detached entity using update()
, but the session already has another persistent instance with the same identifier (primary key).
🔹 Why does it happen?
- Hibernate ensures that within a single session, there can be only one managed (persistent) object representing a given database row (primary key).
- If you try to
update()
a detached object with the same ID while another object with that ID is already loaded in the session → Hibernate throwsNonUniqueObjectException
.
🔹 Example showing how it happens:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
// 1) Load entity → becomes persistent
User persistentUser = session.get(User.class, 1L);
// 2) Later, you try to update a detached instance with same ID
User detachedUser = new User();
detachedUser.setId(1L); // same primary key as persistentUser
detachedUser.setUsername("new_username");
session.update(detachedUser); // 💥 Boom! NonUniqueObjectException
tx.commit();
session.close();
✅ Why? Because:
- The session already manages
persistentUser
with ID=1. - You try to
update()
another object (detachedUser
) with the same ID. - Hibernate sees two objects representing the same row in one session → throws
org.hibernate.NonUniqueObjectException
.
🔹 How to avoid it?
✅ Instead of update()
, use session.merge(detachedUser)
:
User managedUser = (User) session.merge(detachedUser); // merges state into existing persistentUser
merge()
copies the detached object’s state into the persistent one → no duplicate, no exception.
✅ Key takeaway:
You get NonUniqueObjectException
if you call update()
with a detached object whose ID matches an already-managed entity in the same session.
Use merge()
instead when you can’t guarantee there’s no persistent instance with the same ID.
Would you like a full example comparing update()
and merge()
behavior side by side?