【问题标题】:How to update JPA entities如何更新 JPA 实体
【发布时间】:2012-11-16 22:15:55
【问题描述】:

我有一个网络应用程序。如果我不使用应用程序(命令行)对数据库进行更改,我的实体不会显示此更改。

有没有办法让实体知道数据已更改并且需要更新?

【问题讨论】:

  • 这是因为 JPA 使用了缓存。如果您重新启动应用服务器,则会检测到更改。
  • @jahroy 有没有办法强制所有实体更新?
  • 我确信有一些方法可以配置 JPA 使用缓存的方式。你得研究一下。我怀疑是否有一种(简单的)方法可以向 JPA 发送消息以从您的数据库客户端更新其缓存。这里有一个相关的问题可能会帮助您入门:stackoverflow.com/q/2809275/778118

标签: java jakarta-ee jpa persistence


【解决方案1】:

虽然可能不是最优雅的解决方案,但您可以尝试在实体管理器上调用refresh()。看到这个答案:Java JPA - Sync Database and Entity

或者,您可以使用pessimistic locks 来防止在使用您的实体时数据意外更改。

【讨论】:

    【解决方案2】:

    JPA 不是数据库观察者,底层的 JDBC 也不是。无法从数据库服务器通知您的某些实体包含旧的或不存在的数据。唯一知道的方法是刷新或尝试提交当前事务。

    【讨论】:

    • 这是对的,但是否可以将 JPA 配置为不使用缓存?
    • @jahroy 这取决于提供者。 JPA 作为规范并没有说明任何关于缓存的内容,而是将其留给了实现者。
    【解决方案3】:

    您的问题是您使用的是资源本地事务类型。您有义务设计您的事务 begin() 和 commit() - 技术上称为事务分界。如果 EntityManager 保存时间过长,可能会导致数据过时——就像您的投诉一样——甚至会导致内存泄漏和性能下降。您必须制定自己的交易管理政策。

    另一方面,您可以通过为 GlassFish 之类的应用程序服务器进行开发来避免头痛,将为通常由服务器注入的线程安全 EntityManager 创建一个 JTA 事务类型。因此,您可以保存所有交易管道。

    我的论点是指引用第 294 页的 JSR-317 JPA 规范:

    当容器管理的实体管理器在活动 JTA 事务的范围内被调用时,一个新的持久性上下文开始……持久性上下文被创建,然后与 JTA 事务相关联。 当关联的 JTA 事务提交或回滚时,持久性上下文结束,并且由 EntityManager 管理的所有实体都变得分离。

    请参考my answer in this post for the steps to setup a JTA transaction type in GlassFish.

    一个提示

    如果您需要优先考虑在应用程序之外完成的数据库更新,而不是当前 EntityManager 中的更新(即 JTA 事务)操作。然后使用 EntityManager.refresh() 方法丢弃当前未完成的事务操作,直到 refresh() 调用并诉诸数据库最新状态。

    【讨论】:

      猜你喜欢
      • 2016-11-16
      • 2014-02-10
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      • 2012-08-06
      • 2020-05-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多