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

Reply