442 words

remove() and persist() in same transaction => Attempt to reuse an existing primary key value

#1
2017-02-22 06:53

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?

btc_es
btc_es's picture
Joined on 2014-10-20
User Post #169
#2
2017-02-24 09:38

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
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #2,704
#3
2017-03-09 17:00

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

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #2,711
#4
2017-03-17 15:12

Thank you for the fix. It works.

btc_es
btc_es's picture
Joined on 2014-10-20
User Post #173

Post Reply

Please read carefully the posting instructions - before posting to the ObjectDB website.

  • You may have to disable pop up blocking in order to use the toolbar (e.g. in Chrome).
  • Use ctrl + right click to open the browser context menu in the editing area (e.g. for using a browser spell checker).
  • To insert formatted lines (e.g. Java code, stack trace) - select a style in the toolbar and then insert the text in the new created block.
  • Avoid overflow of published source code examples by breaking long lines.
  • You may mark in paragraph code words (e.g. class names) with the code style (can be applied by ctrl + D).
  • Long stack traces (> 50 lines) and complex source examples (> 100 lines) should be posted as attachments.
Attachments:
Maximum file size: 32 MB
Cancel