Remove a modified entity cause an optimistic lock exception

#1

Hello,

the following examples load and modify an entity, and load and remove the same entity.

The first example 'SetAndRemoveIssue.java' is a simple java program which executes without errors.

The second example is an OSGi program which fails with an optimistic lock exception.

Both examples are equivalent, please execute SetAndRemoveIssue.java (in the OSGi example as a plugin-test).

Can you explain the optimistic lock exception?

It seems that the first level cache contains yet a dirty entity although the former query has cause an automatically flush.

Best regards

#2

We started exploring your question, but the size of the OSGI test case makes progress very slow. Thanks for writing a minimal Java console test case. However, since it behaves differently and you may need the OSGi example in order to demonstrate the issue, it would help if you can minimize the OSGi test case to the minimum that can still show the unexpected behaviour (i.e. remove unnecessary bundles, entity classes, JPA wrappers, etc.)

ObjectDB Support
#3

I created a minimum OSGi example.

Please clean and build the example in eclipse before you execute the plugin test SetAndRemoveIssue.

#4

The OSGi test is based on:

  • Retrieving an object from the database.
  • Modifying the object.
  • Flushing changes to the database (by running a query in FlushModeType.AUTO?)
  • Removing the object.
  • Committing the changes.

The console application is the same but without the flush.

Accordingly the following console application includes flush before remove and throws an OptimisticLockException. Please confirm that it is equivalent to the OSGi example by demonstrating the same issue.

import javax.persistence.*;

public class T1757 {   

    public static void main(String[] args) {
        EntityManagerFactory emf =
            Persistence.createEntityManagerFactory(
                "objectdb:$objectdb/db/test.tmp;drop");

        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        em.persist(new MyEntity());
        em.getTransaction().commit();
        em.close();

        em = emf.createEntityManager();
        em.getTransaction().begin();
        MyEntity e = em.find(MyEntity.class, 1);
        e.increaseValue();
        em.flush();
        em.remove(e);
        em.getTransaction().commit();
        em.close();

        emf.close();
    }

    @Entity
    public static class MyEntity {
        @Version long version;
        int value;
        void increaseValue() {
            value++;
        }
    }
}
ObjectDB Support
#5

Yes, I have been run your example in our OSGi environment.

The behavior is equivalent.

It throws an OptimisticLockException.

#6

I have changed your example which is more compatible with our OSGi example.

But the exception does not occur in this changed example, the exception is only caused in our OSGi example.

I believe you must debug the OSGi example to analyze the issue.

 

public class T1757 {  
 
    public static void main(String[] args) {
        EntityManagerFactory emf =
            Persistence.createEntityManagerFactory(
                "objectdb:$objectdb/db/test.tmp;drop");

        EntityManager em = emf.createEntityManager();
        em.setFlushMode(FlushModeType.AUTO);
        em.getTransaction().begin();
        em.persist(new MyEntity());
        em.getTransaction().commit();
        em.close();

        em = emf.createEntityManager();
        em.getTransaction().begin();
        MyEntity e = (MyEntity)em.createQuery("select m from MyEntity m").getSingleResult();
        e.increaseValue();
        e = (MyEntity)em.createQuery("select m from MyEntity m").getSingleResult();
        em.remove(e);
        em.getTransaction().commit();
        em.close();

        emf.close();
    }

    @Entity
    public static class MyEntity {
        @Version long version;
        int value;
        void increaseValue() {
            value++;
        }
    }
}

 

#7

Almost every issue in an OSGi application exists also in non OSGi applications and can be demonstrated with a simple console application. In your last post FlushModeType.AUTO is set to the wrong EntityManager, i.e. to the one that is used to persist the object rather than to the EntityManager that is created later to retrieve the object.

Anyway, thank you for reporting this issue. Please try build 2.6.4_04 that should fix it.

ObjectDB Support

Reply