Java 冬眠+&引用;“关于重复键”;逻辑

Java 冬眠+&引用;“关于重复键”;逻辑,java,mysql,hibernate,duplicates,Java,Mysql,Hibernate,Duplicates,我正在寻找一种方法来保存或更新记录,根据表的唯一键(由几列组成) 我想实现INSERT使用的相同功能。。。重复密钥更新时——意味着盲目保存记录,并让DB/Hibernate插入新记录,或者如果唯一密钥已经存在,则更新现有记录 我知道我可以使用@SQLInsert(sql=“INSERT-INTO..ON-DUPLICATE-KEY-UPDATE”),但我不希望自己编写SQLs,而是让Hibernate来完成这项工作。(我认为它会做得更好——否则为什么要使用Hibernate?这听起来不是一个干净

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

我想实现
INSERT使用的相同功能。。。重复密钥更新时
——意味着盲目保存记录,并让DB/Hibernate插入新记录,或者如果唯一密钥已经存在,则更新现有记录


我知道我可以使用
@SQLInsert(sql=“INSERT-INTO..ON-DUPLICATE-KEY-UPDATE”)
,但我不希望自己编写SQLs,而是让Hibernate来完成这项工作。(我认为它会做得更好——否则为什么要使用Hibernate?

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

编辑

或者也许考虑MurGe()是否是你所要寻找的:

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

您可以从会话类中使用saveOrUpdate()。

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

您只有在调用
flush()
后才会得到异常,因此您应该确保这也在try-catch块中

如果首先检查行是否存在,我会小心地实施解决方案。如果多个会话同时更新表,则可能会得到竞争条件。两个进程几乎同时读取该行以查看它是否存在;它们都检测到它不在那里,然后它们都尝试创建一个新行。谁赢谁输谁输


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

您最好使用On Dup Key路由…我想我现在确实只使用On Dup Key…
saveOrUpdate()
无法解决此问题,特别是在Galz描述的用例中<代码>保存或更新将尝试在设置了标识符(且未分配该标识符)时更新,如果是新对象实例,则尝试插入(无论数据库中是否存在具有相同标识符的记录)。我不确定,因为在使用“on DUPLICATE KEY”进行更新/插入之前,数据库本身也需要先检查行是否存在。此外,我不确定所有数据库服务器(如MS-SQL)是否都支持on DUPLICATE KEY。我认为DB将能够更有效地使用索引-如果我插入了100条记录,我可以循环使用它们并运行100个不同的SELECT查询和100个不同的insert/UPDATE查询,或者以某种方式使用
IN()
?在我看来,在DB上更安全(我在非常大的DBs中使用了一段时间的DUP键,非常有效)。