Hello Support,
in our configuration (FlushModeType.AUTO) is the execution of em.find(Entity.class, <id>) much faster than an equivalent query.
To optimize the Performance we define a special Entity (A) with additional data that use an existing ID of another Entity (B) from another class (another table). On this point we get no conflicts.
If we remove additional data for Entity (B) and then the special Entity (A) is empty, we remove the special Entity (A).
If we add additional data for Entity (B) we check if an Entity (A) with the ID of Entity (B) exist. If it exist we put the date to the existing otherwise we create it.
Now we got the problem that we try to do two thinks in the same transaction:
first remove additional Data -> The special Entity (with id 1) is empty and we remove() it.
then we add additional Data -> It not exist an special Entity (with id 1) theerfor we create and persit() it.
Then we get the following exception:
com.objectdb.o.UserException: Attempt to reuse an existing primary key value (Persist_Remove_Persist$EntityA:1)
We created a small test, to demonstrate our scenario:
import javax.persistence.Entity; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.FlushModeType; import javax.persistence.Id; import javax.persistence.Persistence; public final class Persist_Remove_Persist { public static void main(String[] args) { EntityManagerFactory emf; emf = Persistence.createEntityManagerFactory("objectdb:$objectdb/db/test.tmp;drop"); EntityManager em = emf.createEntityManager(); em.setFlushMode(FlushModeType.AUTO); System.out.println("create and persist"); em.getTransaction().begin(); EntityA entity = new EntityA(1); em.persist(entity); em.getTransaction().commit(); System.out.println("load and remove"); em.getTransaction().begin(); EntityA persitedEntity = em.find(EntityA.class, 1); em.remove(persitedEntity); // If we call a FLUSH it works. // em.flush(); System.out.println("create and persist AGAIN"); // create a new entity with the same id which was already removed! EntityA entityNew = new EntityA(1); em.persist(entityNew); em.getTransaction().commit(); em.close(); emf.close(); } @Entity public static class EntityA { public EntityA(int id) { this.id = id; } @Id int id; } }
A possible workaround, that this scenario works is to call a flush (see commet) after em.remove(entity);
But this is not efficient, as we are calling it potentially thousands of times.
Is it expected that the commands not executed in the order they are pushed to the context or is it a BUG?