【问题标题】:How best to handle Constraint Violations in Spring JDBC如何最好地处理 Spring JDBC 中的约束冲突
【发布时间】:2018-08-02 20:26:59
【问题描述】:

在 Spring JDBC 中处理约束冲突的最佳/最正确方法是什么?

作为一个真实的例子。我有一个users 表,其中包含url_slugemail 列。这两个都是独一无二的。在创建新记录或更新现有记录时,如果我尝试让一条记录包含此表中另一条记录的重复值,我想将一个合理的错误返回给调用者。

我能想到的唯一选择都是有缺陷的。我在 Postgres 10 中这样做,使用 Spring NamedParameterJdbcTemplate 以防万一。

在执行 INSERT/UPDATE 之前检查数据。

这将涉及对每个插入/更新调用的额外查询,并且有一个竞争条件,这意味着它可能仍然无法捕获它。即

  1. 线程 1 开始事务
  2. 线程 2 开始事务
  3. 线程 1 查询数据
  4. 线程 2 查询数据
  5. 线程 1 确实更新了
  6. 线程 2 确实更新了
  7. 线程 1 确实提交了
  8. 线程 2 确实提交了

处理DuplicateKeyException

这里的问题是它在事务提交之前不会被抛出,此时可能不清楚究竟哪个 SQL 调用失败、哪个约束失败或其他类似情况。

【问题讨论】:

    标签: spring postgresql jdbc spring-jdbc jdbctemplate


    【解决方案1】:

    没有“最好”的方法来处理这类异常,除了将其放入 try catch 块并将错误消息传播回用户。

    当然,在您的示例中,问题是您很可能不想使用Serializable 隔离级别,它本质上是一个接一个地执行每个事务,确保不会发生这种情况。另一种方法是为整个事务锁定表,但我也不建议这样做。

    只需将您的事务调用放入一个 try-catch 块中并根据需要进行处理。

    【讨论】:

    • 有没有一种理智的方法可以从异常中获取实际违规行为?我希望能够准确地向用户展示问题所在,而不是抽象的“出现问题”消息。
    • 我目前还没有准备好的示例,但是如果您从 Spring 获得一般的 DataAccessException,那么我认为您可以使用 getRootCause 方法来获取原始异常。
    • 我之前确实尝试过挖掘它,但异常树中没有任何内容可以为您提供约束名称、列名称或类似的信息,除了消息,它是数据库术语而不是 API 术语,加上暴露内部细节......
    • 如果您找不到任何可以使用的东西,您必须使用“再试一次”之类的一般错误消息。
    猜你喜欢
    • 2015-04-22
    • 2021-05-25
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 2011-01-31
    • 1970-01-01
    相关资源
    最近更新 更多