【问题标题】:Hibernate returns stale Objects when calling findOneHibernate 在调用 findOne 时返回过时的对象
【发布时间】:2014-09-19 14:11:34
【问题描述】:

我正在使用 Spring Data JPA save(Object entity) method 从多线程 Web 应用程序中保存对象。

我偶尔会发现,当我从会话中加载对象时,使用:

findOne(long id)

从会话返回的对象已过时并且不反映数据库中的最新版本。我只保存来自这个应用程序的数据并且只使用一个 Spring Data JPA 实例 界面。

什么可能导致它,我应该如何解决这个问题?

【问题讨论】:

  • 我检查了缓存,它正在使用@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)

标签: java hibernate jpa spring-data-jpa staledataexception


【解决方案1】:

Hibernate 使用 PreparedStatement#executeUpdate 结果来检查更新的行数。如果没有匹配的行,则抛出 StaleObjectStateException(使用 Hibernate API 时)或 OptimisticLockException(使用 JPA 时)。

Optimistic locking 是一种通用并发控制技术,它适用于物理和application-level transactions

因此,当多个并发请求修改相同的共享持久数据时,陈旧异常可以防止“丢失更新”现象。

在应用程序级事务中,一旦加载实体,由于一级缓存(持久性上下文),您将获得逻辑可重复读取,但其他用户仍然可以修改上述实体。

所以你确实可以遇到过时的实体,但是乐观锁定机制可以防止丢失更新而不需要任何额外的数据库锁,它甚至适用于长时间的对话。

【讨论】:

  • 你对其他用户有什么看法?我只有一个应用程序。
  • 即使是单个应用程序也可能被多个并发请求访问。
  • 是的,但所有请求都由单例 EntityManager 处理。 EntityManager 不应该有任何过时的数据。
  • 实体管理器是线程绑定的。这就是我们使用 PersistenceContext 而不是 Resource 或 Inject 的原因。实体管理器不是单例。它是在事务边界上创建的。
猜你喜欢
  • 1970-01-01
  • 2018-08-07
  • 1970-01-01
  • 1970-01-01
  • 2021-02-07
  • 2022-01-23
  • 2018-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多