Java 由于MS SQL中唯一约束的非标准行为,Spring/Hibernate的解决方案

Java 由于MS SQL中唯一约束的非标准行为,Spring/Hibernate的解决方案,java,sql-server,hibernate,spring,Java,Sql Server,Hibernate,Spring,索引上有一个唯一的数据库约束,它不允许多个记录具有相同的列 有一段代码由Hibernate(v2.1.8)管理,执行两个DAO getHibernateTemplate().save(对象) 调用两条输入到上述表中的记录 如果此代码在没有事务的情况下执行,则会生成INSERT、UPDATE、然后是另一个INSERT和另一个UPDATE SQL语句,并且工作正常。显然,顺序是先插入包含DB NULL的记录,然后用正确的数据更新它 如果此代码在单个Spring事务中包装的Spring(v2.0.5)

索引上有一个唯一的数据库约束,它不允许多个记录具有相同的列

有一段代码由Hibernate(v2.1.8)管理,执行两个DAO
getHibernateTemplate().save(对象)

调用两条输入到上述表中的记录

如果此代码在没有事务的情况下执行,则会生成INSERT、UPDATE、然后是另一个INSERT和另一个UPDATE SQL语句,并且工作正常。显然,顺序是先插入包含DB NULL的记录,然后用正确的数据更新它

如果此代码在单个Spring事务中包装的Spring(v2.0.5)下执行,则会导致两次插入,然后由于上述唯一约束而立即发生异常

由于与ANSI SQL不兼容,此问题仅在上显示。它在MySQL和Oracle上运行良好。不幸的是,我们的解决方案是跨平台的,必须支持所有数据库


有了这一堆技术,对于给定的问题,您首选的解决方法是什么?

我没有Hibernate方面的经验,所以我不知道您是否可以随意更改DB,或者Hibernate是否需要您无法更改的特定DB结构

如果可以进行更改,则可以在MSSQL中使用此变通方法模拟ANSI行为:

删除唯一索引/约束

定义如下所示的计算字段:

alter table MyTable Add MyCalcField as 
case when MyUniqueField is NULL 
      then cast(Myprimarykey as MyUniqueFieldType) 
      else MyUniqueField end
在您创建的新字段上添加唯一约束

当然,如果MyUniqueField不是主键,这一点也适用!:)


您可以在

中找到更多详细信息。您可以尝试在两次保存之间刷新hibernate会话。这可能会迫使Hibernate在第二次插入之前执行第一次更新


另外,当您说hibernate使用insert插入NULL时,您是说每一列都是NULL,还是仅仅是ID列?

出于好奇,ANSI SQL在这种情况下定义了什么行为?在具有唯一约束的表中插入两个相同的行似乎会导致约束冲突。ANSI行为是NULL=NULL不为真,因此在唯一约束中应允许两个NULL值