【问题标题】:How to tell if JPA EntityManager.merge is doing an insert or an update如何判断 JPA EntityManager.merge 是在执行插入还是更新
【发布时间】:2014-03-11 21:24:02
【问题描述】:

我正在使用带有 EclipseLink 的 JPA 并调用 EntityManager.merge() 来插入/更新数据库中的记录。这些记录来自外部系统,因此我无法判断它们是新记录还是现有记录的更新。

当我调用merge() 时,有什么方法可以知道 JPA 正在执行哪种操作(插入/更新)?

【问题讨论】:

  • 为了确定幕后发生了什么,您可以启用您的 jpa 提供程序日志以查看 sql 查询。

标签: java jpa eclipselink entitymanager


【解决方案1】:

首先,这种行为对你来说是透明的,所以不会直接告诉你 merge 的作用。

但是由于您没有提供有关合并操作的详细信息,我很难想象您有什么用例,您不知道您是更新还是插入。这方面的问题是

  • 您使用的是生成的 ID 还是手动的 ID?
  • 您使用的是版本列吗?
  • 您是在插入/更新单个实体还是子实体?

【讨论】:

  • 手册 ID,没有版本列,只有单个实体。用例是第 3 方系统向我的 REST 应用程序发送包含更新和新记录的 json,我需要标记新记录和更新记录,因为该应用程序需要与另一台服务器保持同步。我在每个表中都有一个新的、更新的、删除的列,所以如果记录被插入,我需要将 new 设置为 true,如果记录被更新,我需要将其设置为 true。
  • 在这种情况下,我认为您所能做的就是通过其 id 选择每条记录,然后相应地设置您的标志列。
【解决方案2】:

我也想知道这个问题的答案。

我可以想象很多情况,我需要检查对象是否存储新记录或现有记录的值。

为了缩短历史记录,我从外部来源(文件、REST 等)获取记录,我需要知道何时将业务验证应用于一种或另一种表单,并在每种情况下触发正确的操作。

在几篇文章中找到的默认解决方案是使用自动生成的 id 字段。

当我有一个自动生成的 id 时,我可以检查它的值是否为 null(id 在注册表的包含中自动初始化,并在从数据库中获取数据时返回填充)。但是当我没有自动生成的 id 时,或者当它是一个注册表包含但它的值被应用程序或外部源错误地初始化时,这个逻辑不适用(失败得很惨)。

我已对数据库中处理的每条记录进行了查询,但这会导致不必要的过多读取。

另一种方法(需要更多测试)是在名为 isNew 的实体中创建一个瞬态属性。在构造函数中使用 true 值初始化,在 @PostLoad 方法中使用 false 初始化。当记录为新时,构造函数会将对象标记为 isNew = true;读取时,@PostLoad 将标记 isNew = false。

这可能是您的解决方案,或者有人可以告诉我们更好的方法来进行此验证。

【讨论】:

  • 这听起来很聪明。你最后用了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-20
  • 2012-09-24
  • 1970-01-01
  • 2011-07-03
  • 1970-01-01
  • 2010-10-18
  • 1970-01-01
相关资源
最近更新 更多