捕获SQLExceptoin,然后使用SQLException.getSQLState() 并比较它是否是您想要的。
catch (SQLException ex) {
final String ss = ex.getSQLState();
//... blah blah ...
}
有关 SQLState 的详细信息,请参阅PostgreSQL error codes。 (虽然大多数状态类别和代码在 DB 中都是标准的,但并非所有 DB 都以相同的方式实现它们并同时抛出它们,并且大多数 DB 都有特定于 DB 的附加功能)。
没有办法根据 SQLState 捕获异常。不幸的是,您必须抓住它,如果它不是您想要的,则将其包裹并重新扔掉。 (不要不换行就重新抛出,你会丢失原始堆栈)。
在 JDBC 4 中,您可以捕获 SQLException 的子类,例如 SQLNonTransientException,但前提是 JDBC 驱动程序抛出这些子类。在撰写本文时,PgJDBC 不支持这些,并且总是简单地抛出SQLException,所以如果你试图捕捉它们,你将永远不会捕捉到任何东西。 (欢迎使用补丁!)。
在现实世界中,您通常对许多不同的错误条件感兴趣,并希望根据它们做不同的事情。
有点像未经测试的,写在窗口中的东西:
} catch (SQLException ex) {
final String ss = ex.getSQLState();
if (ss.equals("40001") || ss.equals("40P01")) {
/* It is a serialization failure or a deadlock abort. Retry the tx. */
retry_transaction = true;
} else if (ss.startsWith("08") || ss.startsWith("53")) {
/* It is a connection error or resource limit. Reconnect and retry. */
try {
conn.close();
} catch (SQLException ex) {
logger.log("Error closing suspected bad connection after SQLState " + ss, ex);
}
conn = null; /* App knows to reconnect if it sees a null connection */
retry_transaction = true;
} else {
throw new MyAppException(ex);
}
}
...如果您的应用程序在看到空连接时知道要重新连接,并保留它刚刚尝试的事务的记录,以便它可以在循环中重试它,直到它遇到死锁或序列化失败时它成功。
实际上你会比这更聪明,添加重试的速率限制等。这只是一个简单的例子。
有关更多详细信息,请在测试可转换性后将异常转换为PSQLException,或者首先将其捕获为PSQLException。然后通过以下方式获取详细信息:
ex.getServerErrorMessage()
它会为您提供带有详细字段的ServerErrorMessage。