Hibernate:在没有约束的情况下强制SQL唯一性

Hibernate:在没有约束的情况下强制SQL唯一性,sql,hibernate,constraints,unique-constraint,Sql,Hibernate,Constraints,Unique Constraint,我正在使用Hibernate开发一个应用程序。我插入的字段之一在表中必须是唯一的。这里的问题是字段不是主键,并且基础数据库不支持“唯一”约束。所以我必须在我的应用程序代码中强制执行这一点 到目前为止,我已经掌握了以下伪代码: void insert(Data data) { beginTransaction(); boolean exists = existsRecordWithName(data.name); // Line 7 if (exists == false)

我正在使用Hibernate开发一个应用程序。我插入的字段之一在表中必须是唯一的。这里的问题是字段不是主键,并且基础数据库不支持“唯一”约束。所以我必须在我的应用程序代码中强制执行这一点

到目前为止,我已经掌握了以下伪代码:

void insert(Data data) {

  beginTransaction();

  boolean exists = existsRecordWithName(data.name);

  // Line 7

  if (exists == false) {
    insertRecord(data);
  } else {
    display("Name already exists in database!");
  }

  commit();
}
但是,如果两个不同的进程同时插入数据,并且两个进程到达了第7行,他们会认为数据库中没有其他同名记录,他们都会插入->结果是重复的

那么,我怎样才能以这种方式实现唯一性呢?如果我使用纯SQL,我会尝试锁定表,但我正在寻找一个涉及Hibernate标准特性的更高级别的解决方案,因此如果有一天我更改后端,它将继续工作

感谢您的帮助

无法使用应用程序代码强制实施唯一约束。严格来说,约束适用于所有用户。您在应用程序代码中所做的操作仅适用于碰巧使用该应用程序代码的用户。例如,应用程序代码中的约束不适用于使用命令行工具或GUI实用程序访问数据库的DBA或开发人员

话虽如此,SQL DBMS通常支持锁和事务。如果不能通过声明列唯一来强制唯一性,那么下一个最佳选择是显式锁定表,并可能将更改包装到可序列化事务中。我认为锁定表应该足够了,但我不打算在不支持唯一约束的系统上下赌注

什么dbms不支持唯一约束?我敢肯定,我从未见过这样的事情,而且我在大约30年前就开始使用数据库了。

您无法使用应用程序代码强制实施唯一约束。严格来说,约束适用于所有用户。您在应用程序代码中所做的操作仅适用于碰巧使用该应用程序代码的用户。例如,应用程序代码中的约束不适用于使用命令行工具或GUI实用程序访问数据库的DBA或开发人员

话虽如此,SQL DBMS通常支持锁和事务。如果不能通过声明列唯一来强制唯一性,那么下一个最佳选择是显式锁定表,并可能将更改包装到可序列化事务中。我认为锁定表应该足够了,但我不打算在不支持唯一约束的系统上下赌注


什么dbms不支持唯一约束?我敢肯定我从来没有见过这样的事情,我大约30年前就开始使用数据库了。

如果数据库支持,也可以使用hibernate(锁定模式)进行锁定,但使用插入锁定是一件棘手的事情(如何锁定尚不存在的东西)。顺便说一句,如果对该实体执行unique=“true”,会发生什么情况?hibernate是否抛出一个错误说它不能,或者它是否允许重复?我假设您已经正确地实现了equals和hashcode方法


在上面的代码大纲中,您可以对名称进行intern()并围绕名称上的代码执行同步块-这可能会起作用。

如果您的数据库支持,您也可以使用hibernate(锁定模式)进行锁定,但使用insert进行锁定是一项棘手的工作(如何锁定尚未存在的东西)。顺便说一句,如果对该实体执行unique=“true”,会发生什么情况?hibernate是否抛出一个错误说它不能,或者它是否允许重复?我假设您已经正确地实现了equals和hashcode方法


在上面的代码大纲中,您可以对名称进行intern(),并对名称上的代码执行同步块-这可能会起作用。

我尝试将代码封装在可序列化事务中,但没有任何更改。当然,我用PostgreSQL做了一个小测试,结果是一样的。。。我用来检查行是否存在的查询是一个简单的
selectcount(*)
,因此我认为这里的可序列化行为与readcommitted相同。啊,我使用的数据库管理系统是由最终用户强加的一种罕见的适当的东西;-)我试图将代码封装在一个可序列化的事务中,但没有任何更改。当然,我用PostgreSQL做了一个小测试,结果是一样的。。。我用来检查行是否存在的查询是一个简单的
selectcount(*)
,因此我认为这里的可序列化行为与readcommitted相同。啊,我使用的数据库管理系统是由最终用户强加的一种罕见的适当的东西;-)在hibernate映射(使用注释)中设置uniqueConstraints后,我得到了重复的结果。您使用同步块的解决方案可能会成功,但我将把它留给最后的选择;-)事实上,即使这样也只能在单个JVM上工作,如果您有集群设置,您仍然可能会有问题。在hibernate映射中设置uniqueConstraints(使用注释)后,我得到了重复项。您使用同步块的解决方案可能会成功,但我将把它留给最后的选择;-)实际上,即使这样也只能在单个JVM上工作,如果您有集群设置,您仍然可能会遇到问题。