JPA / Hibernate查询返回过时结果

时间:2009-06-17 16:44:51

标签: java hibernate jpa java-ee persistence

我正在使用 EXTENDED 持久上下文,因为它允许我在对象上加载一对多关系,并且在我“合并”一个对象之前也不需要SELECT持久的背景。

我有一个DummyObject:

  1. “上次更新”日期字段

  2. 一对多关系

  3. 通过em.merge(DummyObject)调用,在一个JVM中每 5 秒更新此对象。

    在另一个JVM中,我查询DummyObject进行如下调用

    em.createQuery("from DummyObject").getResultList();  
    

    我每隔 5 秒也会执行此查询。

    问题是,即使Hibernate生成了正确的SQL语句(当我有语句登录时),查询产生的对象都有连续调用后第一个查询的时间戳,而数据库是正确获取更新(我已经验证)。

    我也试过@Version的各种乐观锁定无济于事。 (见评论)

    另一件事是,这在以下情况下可以正常工作:

    1. 我更改了PersistentContextType 到 TRANSACTIONAL (某事 不会允许我懒洋洋地加载 一对多的关系)

    2. 我做了一个EntityManager.clear()调用 在我执行上面的查询之前 (也是不允许的 我懒洋洋地加载了ONE-MANY 关系)。

    3. 为什么我的查询会返回陈旧数据?我已启用二级缓存或查询缓存。

      我做错了吗?我可以通过query.setHint(,)设置一些内容吗?

      也许我不理解“扩展”与 TRANSACTIONAL 正确无误。

3 个答案:

答案 0 :(得分:1)

hibernate会话正在缓存持久对象。因此,由于您要在一个JVM(A)中进行修改并在另一个JVM(B)中进行读取,因此需要刷新B的会话以查看更改。您可以打开新会话或逐出/刷新持久对象。您还可以跨两个JVM复制会话,这可能会解决您的问题。或者您可以尝试将查询更改为仅返回您需要的“DummyObject”部分,并仅在需要时读取持久对象。您也可以尝试无状态会话。

答案 1 :(得分:0)

你在尝试之前尝试过刷新()吗?

答案 2 :(得分:0)

有趣。对我而言,似乎持久化上下文中的实体实例未使用查询结果进行更新。这可能是设计的 - 您可能会通过执行查询而意外覆盖本地更改。

更糟糕的是,JPA无法分离单个实例。您可以清除整个上下文,也可以不清除。所以这也不是一个可能的解决方案。

refresh()类中有一个PersistanceContext方法可以从数据库中获取更改并相应地更新实体实例。但我可以看到这在实际实现中可能不适用。所以我的答案结果是:你可能无法让它发挥作用。