【问题标题】:Hiberanate disable cached resultsHibernate 禁用缓存结果
【发布时间】:2016-03-30 15:31:24
【问题描述】:

我的应用程序有一项服务将在内部轮询作业输出。它会轮询直到作业状态从“进行中”变为“已完成”。另一个系统将在处理作业后将作业状态更新为“已完成”。

这里的问题是,第一次从数据库轮询作业状态时,状态为“进行中”。但后来即使工作状态被其他进程更改,我仍然将其视为“进行中”。问题不在于数据库隔离级别(可重复读取),因为我的休眠查询是在事务外执行的。我怀疑结果被缓存了,当在同一个会话中执行相同的查询时,我得到了缓存的结果。

当在同一个会话中多次执行相同的查询时,如何从数据库中获取更新的数据。

问候, 昌都

【问题讨论】:

  • 并且不查看 Hibernate 日志会告诉您查询去向的答案?!

标签: hibernate jpa spring-boot hibernate-cache


【解决方案1】:

更新

根据 cmets,它是一个使用 Spring JPA 数据的 Spring Boot 应用程序。 service 类每 5 分钟检查一次状态,其中包含一个循环。即,它实际上是在同一个事务中,即同一个会话。

因此,除非我们调用 refresh()evict() and reload,否则我们将无法从数据库中看到更新后的状态。

但问题是CrudRepository 没有公开任何像refresh() 这样我们可以在entity manager 上调用的方法。

所以选项是CrudRepository 并添加一个方法说refreshEntity(...)。此方法将在内部调用entityManager.refresh()。最后service循环可以调用这个refreshEntity(..)方法并获取更新的数据。

举个例子:

public interface MyStatusRepository {
   void refreshEntity(StatusEntity se);
}

public interface StatusRepository extends CrudRepository<StatusEntity, Long>, MyStatusRepository {
    ...
}

@Repository
public class MyStatusRepositoryImpl implements MyStatusRepository {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public void refreshEntity(StatusEntity se); {
        entityManager.refresh(se);
    }
    ...
}

更多关于Extending repository的信息可以在上面的链接中找到。

其他选项是,而不是扩展 CrudRepository,而是在 service 类本身中自动装配 entityManager 并在其上调用 refresh()。这也有效,但会偏离现有设计。

【讨论】:

  • 我没有启用二级缓存。我正在使用带有休眠功能的 Spring Boot,因此我没有明确调用 factory.openSession() 来打开会话。我有扩展 CrudRepository 的 DAO 层。我使用 spring autowired bean 调用 save() 、 fndByName() 等方法来获取和更新结果。如何确保我 evict() 或 refresh() 会话。
  • @chandu 这有点令人困惑。如果你使用 CrudRepository,你甚至不会直接使用session。正确的?当您说service 正在轮询时,它是像@scheduled 注释这样的计划作业还是调用此服务来轮询数据库的人。您能否显示您正在轮询状态更改的service 代码的代码?
  • 你说得对,我不直接使用会话。我的服务循环调用数据库并检查状态。如果是“InProgress”,则线程休眠 5 秒并再次查询数据库。同时,如果作业状态更新,我会中断循环并返回结果。希望现在很清楚
  • @chandu 所以这不是一个预定的工作,有人只打电话给这个service 一次,它会继续循环检查状态。我认为你的service 正在同一事务下运行实际上意味着相同的会话。对吗?
  • 正确我有一个服务用完事务并调用另一个服务层(第二服务层)中的方法。我尝试了第二个服务层,其中包含所有可能的事务传播,例如 NOT_SUPPORTED、REQUIRES_NEW、REQUIRED。但是第二种服务方法仍然给我与第一次调用相同的结果。
猜你喜欢
  • 2011-03-10
  • 2021-04-29
  • 1970-01-01
  • 1970-01-01
  • 2014-10-22
  • 1970-01-01
  • 1970-01-01
  • 2012-10-18
  • 2013-10-06
相关资源
最近更新 更多