Another behavior of transaction isolation level in comparing to 2.8.7

#1

I executed the following example with ObjectDB 2.8.7 a few years ago, it worked.
But with ObjectDB 2.9.5_01 it does not work anymore. It works only, if I uncomment the commit() and begin() in the middle of the main method.
Is this changed behavior expected?

public class nestedTransactionExample {

    static int idCounter = 1;

    public static void main(String[] args) {

        EntityManagerFactory emf;
        emf = Persistence.createEntityManagerFactory("objectdb:./db.tmp;drop");

        EntityManager outerEm = emf.createEntityManager();
        outerEm.setFlushMode(FlushModeType.AUTO);
        outerEm.getTransaction().begin();

        MyEntity outerEntity = new MyEntity();
        outerEntity.strValue = "outer entity";
        outerEm.persist(outerEntity);

        String queryString = "SELECT DISTINCT m FROM MyEntity m";
        TypedQuery<MyEntity> q = outerEm.createQuery(queryString, MyEntity.class);
        q.setHint("objectdb.result-fetch", "LAZY");
        List<MyEntity> firstQueryResult = q.getResultList();
        assertTrue(firstQueryResult.size() == 1);

        EntityManager innerEm = emf.createEntityManager();
        innerEm.setFlushMode(FlushModeType.AUTO);

        innerEm.getTransaction().begin();

        MyEntity innerEntity = new MyEntity();
        innerEntity.strValue = "inner Entity";
        innerEm.persist(innerEntity);
        innerEm.getTransaction().commit();
        innerEm.close();

        //        outerEm.getTransaction().commit();
        //        outerEm.getTransaction().begin();

        TypedQuery<MyEntity> outerQuery = outerEm.createQuery(queryString, MyEntity.class);
        outerQuery.setHint("objectdb.result-fetch", "LAZY");
        List<MyEntity> secondQueryResult = outerQuery.getResultList();

        assertTrue(secondQueryResult.size() == 2);
        assertTrue(secondQueryResult.get(0).strValue != null);
        assertTrue(secondQueryResult.get(1).strValue != null);

        outerEm.getTransaction().commit();
        outerEm.close();
        emf.close();

        System.out.println("All done.");
    }

    @Access (AccessType.FIELD)
    @Entity
    public static class MyEntity {

        public MyEntity() {
            id = idCounter++;
        }

        @Id
        int id;

        @Basic
        String strValue;

    }
}
#2

You are right that in this example outerEm should see two objects in the database after innerEm commits. It is possible that this behavior was changed to resolve a performance issue.
As a workaround, if you want to avoid a manual commit, you can make an additional update to the database before running the query (e.g. of a dummy field in any entity). This will force another flush, ensuring the query executes against a database snapshot that includes both objects.

ObjectDB Support
#3

Can you provide a bug fix in a new ObjectDB version?

 

#4

Possibly. We'll review the implications and assess any potential impact.

ObjectDB Support
#5

no post

#6

It seems that there is a cache issue and you got a previous version of this page, without the last posts. We will investigate it.

ObjectDB Support
#7

Hello, do you already have news regarding the bug fix?

#8

Not yet. We will try to provide an update next week.

ObjectDB Support
#9

It seems that this issue started in build 2.9.4. The regression is a result of the changes introduced to fix another issue (#2964, part 2, posts 15+, where a refresh after a flush could fail).

These changes can be disabled by setting the following system property:

    System.setProperty("objectdb.old-flush-optimization", "true");

Adding this line to the beginning of your test case (referenced in post 1) allows it to pass. You can use this setting to revert to the behavior found in versions up to 2.9.3, including 2.8.7.

Enabling this property means your application will be exposed to the older bug where calling a refresh after a flush fails. However, if your application runs smoothly without encountering those errors, this should serve as a solid workaround for now.

We will continue working to find a permanent solution that resolves both issues simultaneously.

 

ObjectDB Support

Reply