1

The following code:

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test.odb");
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();
    Point p = new Point(0, 0);
    em.persist(p);
    em.getTransaction().commit();
    em.getTransaction().begin();
    Query query = em.createQuery("UPDATE Point SET x = 1001 where x = 0");
    int updateCount = query.executeUpdate();
    em.getTransaction().commit();                
    TypedQuery<Point> myquery = em.createQuery("SELECT p from Point p where p.x = 1001", Point.class);
    List<Point> results = myquery.getResultList();
    System.out.println("X coordinate is: " + results.get(0).getX());
    em.close();

prints out: X coordinate is: 0 which is wrong because X coordinate should be 1001

But if I change the code to:

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test.odb");
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();
    Point p = new Point(0, 0);
    em.persist(p);
    em.getTransaction().commit();
    em.getTransaction().begin();
    Query query = em.createQuery("UPDATE Point SET x = 1001 where x = 0");
    int updateCount = query.executeUpdate();
    em.getTransaction().commit();
    em.close();
    em = emf.createEntityManager();
    TypedQuery<Point> myquery = em.createQuery("SELECT p from Point p where p.x = 1001", Point.class);
    List<Point> results = myquery.getResultList();
    System.out.println("X coordinate is: " + results.get(0).getX());
    em.close();

The result is same as expected:

X coordiate is: 1001

What have I done wrong in the first code snippet?

Ashot Karakhanyan
  • 2,804
  • 3
  • 23
  • 28
user161904
  • 31
  • 1

1 Answers1

1

UPDATE queries bypass the EntityManager, which means that the EntityManager may not have an up to date view of the real objects in the database.

As explained in the UPDATE queries page in the ObjectDB Manual:

"Updating entity objects in the database using an UPDATE query may be slightly more efficient than retrieving entity objects and then updating them, but it should be used cautiously because bypassing the EntityManager may break its synchronization with the database. For example, the EntityManager may not be aware that a cached entity object in its persistence context has been modified by an UPDATE query. Therefore, it is a good practice to use a separate EntityManager for UPDATE queries."

Using a separate EntityManager is exactly what you did by closing and opening a new EntityManager in your revised code.

Alternatively, if you want to use the same EntityManager, you may clear its persistence context (i.e. its cache), after running the UPDATE query and before running the SELECT query.

ObjectDB
  • 1,312
  • 8
  • 9