2010-09-08 114 views
7

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

我想我总是可以尝试插入,如果我发现一个异常做了更新,但是这看起来很拙劣和不理想。任何提示干净的方式来做到这一点?

回答

4

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

它看起来像通过重写这个实体所使用的休眠的sql-insert声明有人did it。如果你不介意不能移植(也可能使用存储过程),请看看。

我想我总是可以尝试插入,如果我发现一个异常做了更新,但是这看起来很拙劣和不理想。任何提示干净的方式来做到这一点?

另一种选择是:

  1. 上唯一键
  2. 进行选择,如果你发现一个记录,更新
  3. 如果你没有找到一个记录,创建

但除非你的过程中锁定整个桌,你可以面对的一些竞争条件多线程和分布式环境以及步骤#3可能会失败。想象一下,两个并发线程:

主题1:

  • 开始反式
  • 执行上的一个键
  • 没有记录一个选择发现
  • 创造纪录
  • 提交

主题2:

  • 开始反式
  • 执行同一个按键上
  • 一个选择没有记录发现
  • 创造纪录
  • 提交(失败!因为线程1是速度更快,具有相同唯一键的记录现在已经存在)

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

3

竞争状态可以用“SELECT ... FOR UPDATE”

+3

如果选择匹配任何行,没有行会被“更新”锁定是可以避免的。竞赛条件是不可避免的。 – 2016-12-17 13:53:40