14

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

我想我总是可以尝试插入,如果我发现异常进行更新,但这似乎很笨拙且不理想。关于清洁方式的任何提示?

4

2 回答 2

10

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

看起来有人通过覆盖Hibernate 用于该实体的语句来做到这一点。sql-insert如果您不介意不便携(并且可能使用存储过程),请查看。

我想我总是可以尝试插入,如果我发现异常进行更新,但这似乎很笨拙且不理想。关于清洁方式的任何提示?

另一种选择是:

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

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

线程 1:

  • 开始反式
  • 对键执行选择
  • 没有找到记录
  • 创建记录
  • 犯罪

线程 2:

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

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

于 2010-09-09T02:18:47.463 回答
2

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

于 2012-07-28T22:55:40.183 回答