处理 Hibernate 的错误代码?

Handling Hibernate's error codes?

考虑一个假设 User table:

-- postgres, but it could have been any other SQL database
CREATE TABLE User(
  id SERIAL PRIMARY KEY,
  mail VARCHAR(32) UNIQUE NOT NULL
);

假设我尝试添加两个具有相同邮件的用户:

session.save(new User(1, "xpto@gmail.com"));
session.save(new User(2, "xpto@gmail.com"));

并通过Hibernate执行。 Hibernate 会给我一个 ConstraintViolationException:

Exception in thread "main" org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:129)

...

Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "users_mail_key"
  Detail: Key (mail)=(xpto@gmail.com) already exists.
        at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
    ...

我想知道的是,除了必须手动解析异常的输出文本之外,是否有一些好的方法来收集错误的原因,以便我可以正确地解释问题并对问题做出反应。

我意识到这实际上可能更多是 Postgres 驱动程序的问题,而不是 Hibernate 的问题,但我在这个阶段不确定,所以我认为在 Hibernate 的上下文中询问可能是合适的。

嗯,在查看 Postgres 驱动程序的源代码后,问题似乎出在 Postgres 而不是 Hibernate。 PSQLException 将包含一些信息,尽管它肯定不像我最初假设的那样完美:(

    } catch (PSQLException e) {
        ServerErrorMessage m = e.getServerErrorMessage();
        System.out.println(m.getColumn());
        System.out.println(m.getConstraint());
        System.out.println(m.getDatatype());
        System.out.println(m.getDetail());
        System.out.println(m.getFile());
        System.out.println(m.getHint());
        System.out.println(m.getInternalPosition());
        System.out.println(m.getInternalQuery());
        System.out.println(m.getLine());
        System.out.println(m.getMessage());
        System.out.println(m.getPosition());
        System.out.println(m.getRoutine());
        System.out.println(m.getSchema());
        System.out.println(m.getSeverity());
        System.out.println(m.getSQLState());
        System.out.println(m.getTable());
        System.out.println(m.getWhere());
    }

打印

null
users_mail_key
null
Key (mail)=(xpto@gmail.com) already exists.
nbtinsert.c
null
0
null
398
duplicate key value violates unique constraint "users_mail_key"
0
_bt_check_unique
public
ERROR
23505
users
null

所以如果你能够从 getSQLState 中得到一个值,你就可以处理异常:

"All messages emitted by the PostgreSQL server are assigned five-character error codes that follow the SQL standard's conventions for "SQLSTATE" 代码。需要知道发生了哪种错误情况的应用程序通常应该测试错误代码,而不是查看文本错误消息。"

发件人:http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html

23505 = unique_violation

注意:在这个 link 中还有列表。