【问题标题】:How to mimic upsert behavior using Hibernate?如何使用 Hibernate 模拟 upsert 行为?
【发布时间】:2011-04-09 22:42:41
【问题描述】:

我正在编写一个应用程序,它将第三方数据源中的实体同步到我们自己的架构中,中间有一个转换/映射步骤。我正在使用 Hibernate 在我们自己的模式中表示和持久化实体。我遇到的一个问题是我的一张表上有一个唯一的多列键。我希望看到的行为类似于 upsert:当 Hibernate 去持久化一个实体并检测到一个唯一的约束违规时,它会进行更新。我们正在使用 MySQL,它提供了 INSERT ... ON DUPLICATE KEY UPDATE 语法,但我不确定如何或是否可以使用 Hibernate?

我想我总是可以尝试插入,如果我发现异常进行更新,但这似乎很老套且不理想。有什么干净的方法可以做到这一点吗?

【问题讨论】:

标签: java hibernate orm upsert


【解决方案1】:

我们正在使用 MySQL,它提供了 INSERT ... ON DUPLICATE KEY UPDATE 语法,但我不确定 Hibernate 如何或是否可以使用它?

通过覆盖 Hibernate 用于此实体的 sql-insert 语句,它看起来像某人 did it。如果您不介意不可移植(并且可能使用存储过程),请查看。

我想我总是可以尝试插入,如果我发现异常进行更新,但这似乎很老套且不理想。有什么干净的方法可以做到这一点吗?

另一种选择是:

  1. 对唯一键执行选择
  2. 如果您找到记录,请更新它
  3. 如果您没有找到记录,请创建它

但除非您在此过程中锁定整个表,否则您可能会在多线程和分布式环境中面临一些竞争条件,并且步骤#3 可能会失败。想象两个并发线程:

线程 1:

  • 开始翻译
  • 对键执行选择
  • 没有找到记录
  • 创建记录
  • 提交

线程 2:

  • 开始翻译
  • 在同一个键上执行选择
  • 没有找到记录
  • 创建记录
  • 提交(失败!,因为线程 1 更快,并且现在存在具有相同唯一键的记录)

所以无论如何你都必须实现某种重试机制(锁定整个表不是 IMO 的好选择)。

【讨论】:

    【解决方案2】:

    通过“select ... for update”可以避免竞争条件

    【讨论】:

    • 如果选择不匹配任何行,“for update”将不会锁定任何行。无法避免竞争条件。
    猜你喜欢
    • 1970-01-01
    • 2022-01-16
    • 2011-06-21
    • 2011-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-23
    相关资源
    最近更新 更多