Java – Hibernate : Downside of merge() over update()

hibernatejavasession

I'm having problems with a NonUniqueObjectException thrown by Hibernate.

Reading the docs, and this blog post, I replaced the call from update() to merge(), and it solved the problem.

I believe I understand the reason for the exception, and why changing the method fixed the problem, in terms of disconnected objects and session boundaries.

My question is : given that merge() will always resolve to the session object, or retrieve it if it doesn't exist, is calling merge() generally a safer alternative than update()?

What is the downside of using merge() over update()?

Best Solution

Is calling merge() generally a safer alternative than update() ?

As a way to avoid NonUniqueObjectException, yes. I think it explains why JPA does not allow an update method.

What is the downside of using merge() over update() ?

An unadvised user may think he or she has a fresh managed entity. Something like

// myEntity (passed as parameter does not become managed)
// Only the one returned by the merge operation is a managed entity
session.merge(myEntity);

// "newValue" is not commited because myEntity is not managed
myEntity.setMyProperty("newValue");

And if your persistence context does not contain your entity, maybe you do not want select-before-updating default behavior. But it can be avoided

  • Add a version (@Version) column. 0 or NULL version indicates that an instance is new and has to be inserted, not updated
  • Use a Hibernate interceptor
  • If you are sure you want to update instead of inserting, you can use the following approach

...

public void updateMyEntity(MyEntity updateableMyEntity);

    // load does not hit the database
    MyEntity myEntity = (MyEntity) session.load(MyEntity.class, updateableMyEntity.getId());

    BeanUtils.copyProperties(myEntity, updateableMyEntity);

}

This way you can update your entity without merge or update method. See this question for more information: Best way to update some fields of a detached object on Hibernate ?