Java + MySQL完整性违规处理

时间:2010-02-04 16:04:28

标签: java jdbc integrity

我使用JDBC(mysql数据库)编写Java程序。 当我违反mysql完整性时(例如,我尝试插入相同的主键值),我抓住 SQL异常。 我应该以它的方式编写它可能永远不会发生(例如,在第一个布尔函数检查主键值是否已经存在于DB中然后调用insert),或者是否可以通过异常处理它? 示例:

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

3 个答案:

答案 0 :(得分:4)

确实基本上有两种方法可以达到这个目的:

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

  2. 根据SQLException#getSQLState()确定被捕获的SQLException的{​​{3}}是否以23开头,这是违反约束的行为。它可能是由比“仅仅”约束违规更多的因素引起的。您不应将每SQLException修改为约束违规。

    public static boolean isConstraintViolation(SQLException e) {
        return e.getSQLState().startsWith("23");
    }
    
  3. 我会选择第一个,因为它在语义上更正确。事实上,这并非特殊情况。你知道它可能会发生。但是,在交互不同步(无意识或优化性能)的繁重并发环境中,它可能会失败。然后,您可能希望确定异常。

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

答案 1 :(得分:2)

有两种可能的答案:

  • 如果您知道您的应用程序旨在避免此类行为,请使用例外
  • 如果您的应用程序经常出现这些错误,请使用测试。

答案 2 :(得分:1)

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

  • 对于“插入前测试”的警告就是每一个 事务将有额外的查询,这将影响性能。当这种错误的交易数量很少时,这尤其是一个更大的问题。
  • “评估SQL异常”的警告就是这样 异常消息是特定于数据库的。这些消息大部分时间都没有 除了说明存在约束违规外,还要提供具体信息。

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

  • 插入前不要进行测试。
  • 让数据库抛出一个 异常。
  • 捕获SQL异常。
  • 在异常流程中(catch 阻止),执行其他查询以形成非常具体的错误消息 向客户说明完全失败的原因(唯一密钥,主键, 外键,特定列等)。

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