Использование запросов на обновление с objectdb

Следующий код:

    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

Что я сделал не так в первом фрагменте кода?


person user161904    schedule 22.04.2014    source источник


Ответы (1)


Запросы UPDATE обходят EntityManager, что означает, что EntityManager может не иметь актуального представления о реальных объектах в базе данных.

Как поясняется на странице запросов UPDATE в Руководстве по ObjectDB:

«Обновление объектов сущностей в базе данных с помощью запроса UPDATE может быть немного более эффективным, чем извлечение объектов сущностей и их последующее обновление, но его следует использовать с осторожностью, поскольку обход EntityManager может нарушить его синхронизацию с базой данных. Например, EntityManager может не имейте в виду, что кэшированный объект сущности в его контексте сохранения был изменен запросом UPDATE. Поэтому рекомендуется использовать отдельный EntityManager для запросов UPDATE».

Использование отдельного EntityManager — это именно то, что вы сделали, закрыв и открыв новый EntityManager в своем исправленном коде.

В качестве альтернативы, если вы хотите использовать тот же EntityManager, вы можете очистить контекст сохранения (т. е. его кеш), после выполнения запроса UPDATE и перед выполнением запроса SELECT.

person ObjectDB    schedule 22.04.2014