ObjectDB ObjectDB

Issue #2027: remove & persist in same transaction => Attempt to reuse an existing primary key value

Type: Bug ReoprtVersion: 2.7.6_08Priority: CriticalStatus: ActiveReplies: 5
#1

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?

edit
delete
#2

Your test case demonstrates a limitation of ObjectDB in removing an entity object and then in the same transaction persisting another object with the same primary key of the removed object.

Obviously a possible workaround is to update the object instead of removing and persisting it.

But we will check if we can release a quick patch to support this without the workaround.

ObjectDB Support
edit
delete
#3

ObjectDB version 2.7.0 fixes this issue. Thank you for the report.

ObjectDB Support
edit
delete
#4

Thank you for the fix. It works.

edit
delete
#5

Build 2.7.5_07 fixes this issue again after unknown regression.

ObjectDB Support
edit
delete
#6

A conflict was found between the fix of this issue and a fix of issue #2153, probably causing the reported regression. Build 2.7.6_08 should now provide a fix that should work for both issue.

ObjectDB Support
edit
delete

Reply

To post on this website please sign in.