Java + MySQL 完整性违规处理

发布于 2024-08-20 06:00:59 字数 262 浏览 7 评论 0原文

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

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

I write Java program using JDBC (mysql database).
When I violate mysql integrity (f.e. I try to insert same primary key value) I catch SQL exception.
Should I write it in way it may never happen (f.e. at first boolean function checking whether primary key value isn't already in DB and then calling insert), or is it okay to handle it just by exception?
Example :

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

谈下烟灰 2024-08-27 06:00:59

实际上,基本上有两种方法可以实现此目的:

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

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

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

我会选择第一个,因为它在语义上更正确。事实上,这并非特例。也就是说,您知道这可能会发生。但在事务未同步(无意中或为了优化性能)的高并发环境中,它可能会失败。然后您可能想要确定异常。

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

There are indeed basically two ways to achieve this:

  1. Test if record exists before inserting --inside the same transaction.

  2. Determine if SQLException#getSQLState() of the catched SQLException starts with 23 which is a constraint violation as per the SQL specification. It can namely be caused by more factors than "just" a constraint violation. You should not amend every SQLException as a constraint violation.

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

I would opt for the first one as it is semantically more correct. It is in fact not an exceptional circumstance. You namely know that it is potentially going to happen. But it may potentially fail in heavy concurrent environment where transactions are not synchronized (either unawarely or to optimize performance). You may then want to determine the exception instead.

That said, you normally shouldn't get a constraint violation on a primary key. In well designed datamodels which uses technical keys as primary keys they are normally to be managed by the database itself. Isn't the field supposed to be an unique key?

千寻… 2024-08-27 06:00:59

有两种可能的答案:

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

There are two possible answers :

  • if you know that your application is designed to avoid this kind of behaviour, use the exception
  • if your application can make these errors often, use a test.
慵挽 2024-08-27 06:00:59

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

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

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

  • 插入前请勿执行测试。
  • 让数据库抛出一个
    例外。
  • 捕获 SQL 异常。
  • 在异常流程中(catch
    块),执行额外的查询以形成非常具体的错误消息
    向客户指示到底发生了什么故障(唯一键、主键、
    外键、特定列等)。

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

As others have mentioned that there are two possible approaches, one is to test and then insert/update otherwise handle SQL Exception. Both these approaches have their downsides:

  • Caveat for "Test before inserting" is that every
    transaction will have additional queries which will impact performance. This is specially a bigger issue when such erroneous transactions are few in number.
  • Caveat for "Evaluating SQL Exception" is that such
    exception messages are very database specific. These messages, most of the time, don't
    give specific information beyond stating that there is constrain violation.

So, I will propose an approach which is hybrid of the two.

  • Don't perform the test before insert.
  • Let database throw an
    exception.
  • Catch SQL Exception.
  • In the exception flow (catch
    block), do additional queries to form very specific error messages to
    indicate customers what has exactly failed (unique key, primary key,
    foreign key, specific columns etc).

This may require few additional lines of code but it definitely improves performance and generates friendly error messages.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文