1

以下代码:

    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

我在第一个代码片段中做错了什么?

4

1 回答 1

1

UPDATE 查询绕过 EntityManager,这意味着 EntityManager 可能没有数据库中真实对象的最新视图。

如ObjectDB 手册中的UPDATE 查询页面所述:

“使用 UPDATE 查询更新数据库中的实体对象可能比检索实体对象然后更新它们稍微高效一些,但应谨慎使用,因为绕过 EntityManager 可能会破坏其与数据库的同步。例如,EntityManager 可能不会请注意,在其持久性上下文中缓存的实体对象已被 UPDATE 查询修改。因此,为 UPDATE 查询使用单独的 EntityManager 是一个好习惯。

使用单独的 EntityManager 正是您通过在修改后的代码中关闭和打开新的 EntityManager 所做的。

或者,如果您想使用相同的 EntityManager,您可以在运行 UPDATE 查询之后和运行 SELECT 查询之前清除其持久性上下文(即其缓存)。

于 2014-04-22T09:14:36.127 回答