Следующий код:
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();
выдает: X-координата: 0, что неверно, потому что координата X должна быть 1001
Но если я изменил код на:
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();
Результат такой же, как и ожидалось:
Координация X: 1001
Что я сделал неправильно в первом фрагменте кода?
Запросы UPDATE обходят EntityManager, что означает, что EntityManager может не иметь обновленного представления реальных объектов в базе данных.
Как поясняется на странице запросов UPDATE в руководстве ObjectDB:
"Обновление объектов объекта в базе данных с помощью запроса UPDATE может быть несколько более эффективным, чем извлечение объектов объекта, а затем их обновление, но его следует использовать осторожно, поскольку обход EntityManager может нарушить его синхронизацию с базой данных. Например, EntityManager может не работать помните, что объект кэшированного объекта в контексте его персистентности был изменен с помощью запроса UPDATE. Поэтому хорошей практикой является использование отдельного EntityManager для запросов UPDATE ".
Использование отдельного EntityManager - это именно то, что вы сделали, закрыв и открыв новый EntityManager в вашем обновленном коде.
В качестве альтернативы, если вы хотите использовать тот же EntityManager, вы можете очистить свой контекст персистентности (т.е. его кеш), после выполнения запроса UPDATE и перед запуском запроса SELECT.