Hibernate +“ON DUPLICATE KEY”逻辑

时间:2011-03-10 11:13:59

标签: java mysql hibernate duplicates

我正在寻找一种方法来保存或更新记录,根据表的唯一键(由多个列组成)。

我希望实现INSERT ... ON DUPLICATE KEY UPDATE使用的相同功能 - 意味着盲目保存记录,让DB / Hibernate插入新的记录,或者如果唯一密钥已经存在则更新现有记录。

我知道我可以使用@SQLInsert( sql="INSERT INTO .. ON DUPLICATE KEY UPDATE"),但我希望不要编写自己的SQL并让Hibernate完成这项工作。 (我假设它会做得更好 - 否则为什么要使用Hibernate?)

3 个答案:

答案 0 :(得分:2)

这对我来说听起来不是一个干净的方法。最好首先查看具有给定密钥的实体是否存在。如果是,请更新并保存,如果没有创建新的。

修改

或者考虑一下merge()是否正在寻找:

  • 如果存在具有当前与会话关联的相同标识符的持久性实例,则将给定对象的状态复制到持久性实例
  • 如果当前没有与会话关联的持久性实例,请尝试从数据库加载它,或者创建新的持久性实例
  • 返回持久化实例
  • 给定的实例没有与会话关联,它仍然是分离的

< http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html

答案 1 :(得分:2)

当您尝试插入破坏约束的行(包括唯一约束)时,Hibernate可能会抛出ConstraintViolationException。如果你没有得到那个异常,你可能会得到一些其他一般的Hibernate异常 - 它取决于Hibernate的版本以及Hibernate将MySQL异常映射到你的数据库版本和类型中的Hibernate异常的能力使用(我还没有对所有内容进行过测试)。

您只会在调用flush()后获得异常,因此您应该确保它也在您的try-catch块中。

我会小心实现解决方案,您首先检查该行是否存在。如果多个会话同时更新表,则可能会出现竞争条件。两个进程几乎同时读取该行以查看它是否存在;他们都发现它不存在,然后他们都试图创建一个新行。一个人将失败取决于谁赢得比赛。

更好的解决方案是首先尝试插入,如果失败,则认为它已经存在。但是,一旦有异常,您将不得不回滚,因此这将限制您使用此方法的方式。

答案 2 :(得分:0)

您可以使用Session类中的saveOrUpdate()。