简体   繁体   English

JPA/Hibernate 查询返回过时的结果

[英]JPA/Hibernate Query Returns Stale Results

I am using an EXTENDED Persistent Context because it will allow me to Lazily Load a one-many relationship on an object and it also won't require a SELECT before I "merge" an object with the persistent context.我正在使用扩展持久上下文,因为它允许我在 object 上延迟加载一对多关系,并且在我将 object 与持久上下文“合并”之前,它也不需要 SELECT。

I have an DummyObject with:我有一个 DummyObject:

  1. A "Last Updated" Date Field “最后更新”日期字段

  2. A One-Many Relationship一对多关系

This Object is being updated every 5 seconds in one JVM through a em.merge(DummyObject) call.这个 Object 通过em.merge(DummyObject)调用在一个 JVM 中每5秒更新一次。

In another JVM, I query for the DummyObject doing a call like the following在另一个 JVM 中,我查询 DummyObject 执行如下调用

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

I am also doing this Query every 5 seconds.我也每5秒执行一次此查询。

The problem is, is that the Objects resulted from the Query all have a Timestamp of the very first Query after successive calls, even though Hibernate is generating the correct SQL statement (when I have statement logging on), and the Database is getting the updates correctly (I have verified).问题是,即使 Hibernate 正在生成正确的 SQL 语句(当我有语句登录时),查询产生的对象都具有连续调用后第一个查询的时间戳,并且数据库正在获取更新正确(我已经验证)。

I have also tried all sorts of optimistic locking with @Version to no avail.我也尝试过使用@Version 进行各种乐观锁定,但均无济于事。 (See comments) (看评论)

Another thing is that this does work correctly when:另一件事是,这在以下情况下确实可以正常工作:

  1. I change the PersistentContextType to TRANSACTIONAL (something that will not allow me to lazily load the ONE-MANY relationship)我将 PersistentContextType 更改为TRANSACTIONAL (不允许我延迟加载 ONE-MANY 关系的东西)

  2. I do an EntityManager.clear() call before I do the Query above (Something that will also not allow me to lazily load the ONE-MANY relationship).在执行上面的查询之前,我执行了一个 EntityManager.clear() 调用(这也不允许我延迟加载 ONE-MANY 关系)。

Why does my Query return stale data?为什么我的查询返回陈旧数据? I have no Second Level Caching or Query Caching enabled.没有启用二级缓存或查询缓存。

Am I doing something wrong?难道我做错了什么? Is there something I can set through query.setHint(, )?我可以通过 query.setHint(, ) 设置什么吗?

Maybe I don't understand " EXTENDED " vs TRANSACTIONAL correctly.也许我没有正确理解“ EXTENDED ”与TRANSACTIONAL

The hibernate session is caching the persistent objects. hibernate session 正在缓存持久对象。 So because you are modifying in one JVM (A) and reading in another JVM(B), B's sessions needs to be refreshed to see the changes.因此,因为您正在修改一个 JVM (A) 并在另一个 JVM(B) 中读取,所以需要刷新 B 的会话以查看更改。 You could open a new session or evict/refresh the persistent objects.您可以打开一个新的 session 或逐出/刷新持久对象。 You can also replicate the sessions across both JVMs which might take care of your problem.您还可以跨两个 JVM 复制会话,这可能会解决您的问题。 Or you could try changing the query to only return pieces of the 'DummyObject' which you need and only read the persistent object when it is required.或者您可以尝试更改查询以仅返回您需要的“DummyObject”片段,并且仅在需要时读取持久性 object。 You might also try a stateless session.您也可以尝试无状态的 session。

Have you tried doing a flush() before your fetch?您是否尝试过在获取之前执行 flush()?

Interesting.有趣的。 To me it seems that the entity instance in your persistence context is not updated with the results from the query.在我看来,您的持久性上下文中的实体实例似乎未使用查询结果进行更新。 This might be by design - you could accidentally overwrite local changes by executing a query.这可能是设计使然——您可能会通过执行查询不小心覆盖本地更改。

What's worse is that there is no way in JPA to detach a single instance.更糟糕的是,JPA 中没有办法分离单个实例。 You either clear the entire context or you don't.您要么清除整个上下文,要么不清除。 So that is not a possible solution either.所以这也不是一个可能的解决方案。

There is a refresh() method available in the PersistanceContext class that grabs changes from the database and updates the entity instance accordingly. PersistanceContext class 中有一个refresh()方法可用,它从数据库中获取更改并相应地更新实体实例。 But I can see how that might not be applicable in an actual implementation.但我可以看出这在实际实施中可能不适用。 So my answer turns out to be: you probably can't get it to work.所以我的回答是:你可能无法让它工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM