5

我使用 JDBC(mysql 数据库)编写 Java 程序。当我违反 mysql 完整性(我尝试插入相同的主键值)时,我捕获SQL 异常。 我应该以它可能永远不会发生的方式编写它(首先是布尔函数检查主键值是否已经在数据库中,然后调用插入),还是可以通过异常处理它?例子 :

catch (SQLException ex) {ex.printStackTrace(); showSomeErrorDialog(); }
4

3 回答 3

4

确实基本上有两种方法可以实现这一点:

  1. 在同一事务中插入 --inside 之前测试是否存在记录。

  2. 根据SQL 规范确定SQLException#getSQLState()捕获的SQLException开头23是否违反约束。它可能是由更多的因素引起的,而不仅仅是“违反”约束。您不应该将每个都修改为违反约束。SQLException

    public static boolean isConstraintViolation(SQLException e) {
        return e.getSQLState().startsWith("23");
    }
    

我会选择第一个,因为它在语义上更正确。事实上,这并不是一个例外情况。你即知道它可能会发生。但它可能会在事务不同步的重并发环境中失败(不知不觉地或优化性能)。然后,您可能想要确定异常。

也就是说,您通常不应该在主键上违反约束。在使用技术键作为主键的精心设计的数据模型中,它们通常由数据库本身管理。该字段不应该是唯一键吗?

于 2010-02-04T16:37:16.743 回答
2

有两个可能的答案:

  • 如果您知道您的应用程序旨在避免这种行为,请使用异常
  • 如果您的应用程序经常出现这些错误,请使用测试。
于 2010-02-04T16:10:49.050 回答
1

正如其他人提到的,有两种可能的方法,一种是测试然后插入/更新,否则处理 SQL 异常。这两种方法都有其缺点:

  • “插入前测试”的警告是每个事务都会有额外的查询,这会影响性能。当此类错误交易数量很少时,这尤其是一个更大的问题。
  • “评估 SQL 异常”的警告是此类异常消息非常特定于数据库。在大多数情况下,这些消息除了说明存在约束违规外,不会提供具体信息。

因此,我将提出一种将两者混合的方法。

  • 插入前不要执行测试。
  • 让数据库抛出异常。
  • 捕获 SQL 异常。
  • 在异常流(catch 块)中,执行额外的查询以形成非常具体的错误消息,以指示客户究竟是什么失败了(唯一键、主键、外键、特定列等)。

这可能需要几行额外的代码,但它肯定会提高性能并生成友好的错误消息。

于 2016-02-02T08:52:26.937 回答