【问题标题】:Merge detached JPA entity with @version field将分离的 JPA 实体与 @version 字段合并
【发布时间】:2015-10-24 22:37:42
【问题描述】:

我有一个带有 @Version 字段的 JPA 实体类,用于乐观锁定。我需要merge() 一个分离的实体实例,它的版本字段在持久性上下文中的现有实体实例上未初始化。执行此操作时,托管实例的版本字段会被覆盖,这会导致稍后出现 OptimisticLockException。

我可以在合并之前手动将版本字段的内容从托管实体复制到分离实体,但我觉得这有点尴尬。是否有更好的选择或最佳实践来处理这种情况?

【问题讨论】:

  • 为什么版本字段会未初始化?您尝试合并的这个实体是在分离之前从数据库加载的吗?是这样的,版本字段应该在检索时已经设置好了。
  • 分离的实体不是从数据库中读取的,而是从外部 CSV 文件中的数据构建的。该文件中的数据应该用于批量更新整个数据库。

标签: java jpa


【解决方案1】:

如果版本字段未初始化,则合并将不起作用。它必须在那里。 JPA 提供者必须将您尝试合并的实体的版本字段与数据库中的版本进行比较。如果实体版本比数据库中的版本旧,则必须抛出异常。

除了合并之外,您可以做的是通过 JPA 查询使用更新:

Query q = em.createQuery("UPDATE MyEntity me SET me.versionField = me.versionField + 1....");
q.executeUpdate();

您可以在此查询中设置实体的其他字段,但重要的是您必须显式增加版本字段的值。版本字段不会在通过查询更新时自动递增。

【讨论】:

  • 该实体有其他关联实体和相当多的字段要合并。我不想手动执行此操作,但让 entitymanager 进行合并。如果没有版本字段,这很容易:
  • 是否也可以将版本值存储到 CSV 文件中?这样当您构建实体时,版本字段将被初始化。
  • 从 csv 数据创建分离的实体,然后 merge() 整个对象图。使用版本字段,我必须将根实体find()到持久性上下文中,然后将托管版本中的版本合并到分离对象图中,然后合并()。到目前为止对我来说最简单的解决方案,但它仍然看起来很丑。
  • csv 文件是由外部提供者创建的,所以在创建分离实体时我没有版本号。
  • 实体是否期望被多个进程或线程同时更新?如果不是,您可能不需要乐观锁定,那么您可以摆脱版本字段。如果这不是一个选项,那么您只需在进行合并之前查询实体的版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
  • 2012-12-26
  • 2017-06-05
  • 2012-05-17
  • 2011-09-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多