1

I have an entity that I need to copy with JPA. My first thought was to set the ID to null and call EntityManager.persist(entity). However this causes the following error detached entity passed to persist.

Searching on Stack I found this question Cloning JPA entity, which states that calling detach, then set to null and finally persist should work. But it doesn't seem to work as the error is already caused by my entity being detached.

Then I thought, well I should go from detached to transient so that I can call persist. But once again I couldn't find any pleasing answer, Can an object state change from detached to transient.

Do you have any idea how to completely remove an entity from the persistence context, set its ID to null and persist it as a new entity with another ID?

Elbbard
  • 2,064
  • 6
  • 30
  • 53
  • Put the code of your entities, DAOs and Services. The detach method works perfectly and allows the id to be set to null and the entity can be reinserted. – JLazar0 Aug 13 '20 at 16:41
  • 2
    Usually 'detached entity passed to persist' means the entity you detached is referenced by another persistent entity. If you want to use the 'cloning' approach, you would have to make sure no other persistent objects referencing the entity are loaded into the persistence context, or that the entities referencing the detached entity are themselves detached – crizzis Aug 13 '20 at 21:23

1 Answers1

0

This is not an Answer,
but just was facing kinda similar issue/purpose.
So want to share some thoughts.

  • (Idk why OP's case doesnt work.)

  • (I didnt answer "how to make a detached entity into transient")

in_short

If you have a detached entity, say rock_detached,
and if you remove the id of rock_detached,
rock_detached.setIdSql(null);
->
it seems Hibernate will not treat rock_detached as a detached entity anymore
-- it will treat it as a new entity & insert it (when you call em.persist()).

  • Though, Im very Unsure if this is the correct way to do the thing
    --ie: I do wonder what is the correct way to "convert a detached entity to a new entity" (besides setting the id to Null)

misc (-- below are not important)

Why I had such problem::
  1. I have 2 classes NodeMovedEvent & Node
  2. NodeMovedEvent has a Node inside
  3. P1 -> I persist NodeMovedEvent AA with Node NN inside -> good
  4. P2 -> Node NN is used in diff method calls & is detached from entityManger (& potentially modified)
  5. P3 -> I persist NodeMovedEvent BB with Node NN inside -> org.hibernate.PersistentObjectException: **detached** entity passed to persist:
  6. I could - but I dont want to reattach by merge() Node NN
    -- I want a new Node NN_snapshot to be persist with the NodeMovedEvent BB
    -- this kinda correspond to OP's I have an entity that I need to **copy** with JPA
  7. P4 -> so I came up with the idea of "setting the id to Null" -> and it works
    (btw, @Audited wasnt suitable in my case)
For a simpler code example that shows rock_detached.setIdSql(null);::

(could made it simpler without cascade involved, but ...)

enter image description here

  • Ball corresponds to NodeMovedEvent above
  • Rock corrsponds to Node above


Update

@note::
If you are in a multi-threading environment,
make sure you call rock_detached.setIdSql(null); at the last second -- right before you call em.persist() & inside the thread calls em.persist()

  • (otherwise, the rock_detached may have an id set again (after it was null-ed) somewhere before you switch to the thread calls em.persist())
  • (& you should still be aware of the Cascade persist (if you are using it))

Update Misc

again, be aware that, in multi threading,
the time you pass the persist job to thread &
the time actual persist happen
is diff
-- entity may have changed in the meantime.

so, setting id to null may not guarantee the "copy effect" you want -- when in an async design

[[a bit feeling of this was not done right]]

Nor.Z
  • 555
  • 1
  • 5
  • 13