Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to replace an entity using EntityManager

I'm using the JPA EntityManager to do some operations, and one such operation is replacing an entity with another entity that has the same @Id. So, given an oldObject and a newObject, what's the best way to remove the oldObject and replace it with the newObject?

Here's some code that doesn't work:

try
{
    entityManager.getTransaction().begin();
    entityManager.remove(oldObject);
    entityManager.persist(newObject);
    entityManager.getTransaction().commit();
}
catch (PersistenceException persistExc)
{
    entityManager.getTransaction().rollback();
    // do some stuff
}

This code gets the following exception:

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.depressio.SomeObject
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1215)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1148)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1154)
    at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:678)

Now, of course it works OK if instead of removing the entity, I just update its fields that have changed. However, I'm just being given the new object (the UI is tossing it at me via REST), so I really don't have any clue what fields have changed, so I'd have to update every field. If there's a ton of fields, that's not ideal.

I think I'm a little confused as to how to actually do a delete properly. I thought EntityManager.remove was the right way, but I guess not.

Thanks in advance!

Edit 1: I feel I should note that oldObject.id == newObject.id. The id is generated through a @SequenceGenerator. Am I allowed to persist objects with identifiers if their identifier is annotated with a generator already?

Edit 2: According to the top upvoted answer here, because the @Id is already defined and it's an auto-generated field, Hibernate is deeming it detached. Now I know why I get the exception, but the solution is still unclear.

like image 346
Depressio Avatar asked May 31 '13 22:05

Depressio


1 Answers

That's what EntityManager.merge() does. Pass it the new, detached entity, and it will merge its state to the old, attached entity. The detached entity will stay detached, and the old one will stay attached, but have its state replaced by the state of the new, detached one.

like image 52
JB Nizet Avatar answered Sep 22 '22 22:09

JB Nizet