【问题标题】:Proper way to insert record with unique attribute插入具有唯一属性的记录的正确方法
【发布时间】:2016-01-02 22:02:28
【问题描述】:

我正在使用 spring、hibernate 和 postgreSQL。

假设我有一张如下所示的表格:

CREATE TABLE test
(
  id integer NOT NULL
  name character(10)
  CONSTRAINT test_unique UNIQUE (id)
)

所以当我插入记录时,属性 id 应该是唯一的

我想知道插入新记录的更好方法(在我的 spring java 应用程序中):

1) 检查给定 id 的记录是否存在,如果没有插入记录,如下所示:

if(testDao.find(id) == null) {
    Test test =  new Test(Integer id, String name);
    testeDao.create(test);
}

2) 直接调用create方法,等待是否抛出DataAccessException...

Test test =  new Test(Integer id, String name);
try{
    testeDao.create(test);
}
catch(DataAccessException e){
    System.out.println("Error inserting record");
}

我认为第一种方式是合适的,但这意味着对 DB 进行更多处理。你有什么意见?

提前感谢您的任何建议。

【问题讨论】:

    标签: java mysql spring hibernate postgresql


    【解决方案1】:

    选项 (2) 受制于竞争条件,其中并发会话可以在检查和插入之间创建记录。此窗口比您预期的要长,因为该记录可能已被另一个事务插入,但尚未提交。

    选项 (1) 更好,但会导致 PostgreSQL 错误日志中出现大量噪音。

    最好的方法是使用 PostgreSQL 9.5 的 INSERT ... ON CONFLICT ... 支持来执行可靠的、无竞争条件的 insert-if-not-exists 操作。

    在旧版本上,您可以在 plpgsql 中使用循环。

    当然,这两个选项都需要使用原生查询。

    【讨论】:

      【解决方案2】:

      取决于您的 ID 来源。如果您自己生成它,您可以断言唯一性并依靠捕获异常,例如http://docs.oracle.com/javase/1.5.0/docs/api/java/util/UUID.html

      另一种方法是让 Postgres 使用 SERIAL 数据类型生成 ID

      http://www.postgresql.org/docs/8.1/interactive/datatype.html#DATATYPE-SERIAL

      如果您必须从不受信任的来源接管,请事先检查。

      【讨论】:

      • 在我的情况下,id 取自用户提交的表单(好吧,它不完全是 id,而是其他一些列......)所以我应该进行检查,尽管这意味着数据库的更多“负载”,对?
      • 是的,当然。用户输入始终必须被视为最不可信的来源。
      • 通过事先检查,您可能仍然会遇到异常,请参阅 Craigs 的回答
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-02
      • 2020-12-23
      相关资源
      最近更新 更多