如何检测SQ​​LException的SQL错误状态

时间:2013-01-18 18:02:46

标签: java jdbc sqlexception

我正在尝试创建一个JDBC连接池组件,但我遇到了一个问题。那就是:如何检测java.sql.SQLException的错误状态。 据说,州应遵循SQL2003约定中的XOPEN SQL约定和JDK约定。但我找不到关于这两个约定的任何文件。有人可以为我提供吗?

我想知道每个州代表什么,所以我可以决定何时完全关闭连接或重新连接。

我已提到BoneCP的源代码。以下是在发生SQLException时将激活的部分:

    ImmutableSet<String> sqlStateDBFailureCodes = ImmutableSet.of("08001", "08007", "08S01", "57P01", "HY000"); 
    String state = e.getSQLState();
        ConnectionState connectionState = this.getConnectionHook() != null ? this.getConnectionHook().onMarkPossiblyBroken(this, state, e) : ConnectionState.NOP; 
        if (state == null){ // safety;
            state = "08999"; 
        }

        if (((sqlStateDBFailureCodes.contains(state) || connectionState.equals(ConnectionState.TERMINATE_ALL_CONNECTIONS)) && this.pool != null) && this.pool.getDbIsDown().compareAndSet(false, true) ){
            logger.error("Database access problem. Killing off all remaining connections in the connection pool. SQL State = " + state);
            this.pool.connectionStrategy.terminateAllConnections();
            this.pool.poisonAndRepopulatePartitions();
        }
char firstChar = state.charAt(0);
        if (connectionState.equals(ConnectionState.CONNECTION_POSSIBLY_BROKEN) || state.equals("40001") || 
                state.startsWith("08") ||  (firstChar >= '5' && firstChar <='9') /*|| (firstChar >='I' && firstChar <= 'Z')*/){
            this.possiblyBroken = true;
        }

        // Notify anyone who's interested
        if (this.possiblyBroken  && (this.getConnectionHook() != null)){
            this.possiblyBroken = this.getConnectionHook().onConnectionException(this, state, e);
        }

根据这些代码,当{SQLException>的状态等于“08001”,“08007”,“08S01”,“57P01”,“HY000”之一时,boneCP将其视为数据库服务器崩溃。

但为什么,这些州代表什么呢?

3 个答案:

答案 0 :(得分:5)

前{2}个字符在SQL92 specification的“Table_23-SQLSTATE_class_and_subclass_values”中指定。

以下是相关摘录:

00  success completion
01  warning
02  no data
07  dynamic SQL error
08  connection exception
0A  feature not supported
21  cardinality violation
22  data exception
23  integrity constraint violation
24  invalid cursor state
25  invalid transaction state
26  invalid SQL statement name
27  triggered data change violation
28  invalid authorization specification
2A  direct SQL syntax error or access rule violation
2B  dependent privilege descriptors still exist
2C  invalid character set name
2D  invalid transaction termination
2E  invalid connection name
33  invalid SQL descriptor name
34  invalid cursor name
35  invalid condition number
37  dynamic SQL syntax error or access rule violation
3C  ambiguous cursor name
3D  invalid catalog name
3F  invalid schema name
40  transaction rollback
42  syntax error or access rule violation
44  with check option violation
HZ  remote database access

其余字符与数据库供应商有关。因此,通常建议只执行startsWith()检查。

答案 1 :(得分:2)

SQL标准(ISO / IEC-9075),特别是书2基础定义SQL状态。它们是一个2个字符的类值,后跟一个3个字符的子类值。

  

以“0”,“1”,“2”,“3”或“4”之一或简单的拉丁大写字母“A”,“B”之一开头的类值C','D','E','F','G'或'H'仅在ISO / IEC 9075或任何其他国际标准中定义的条件下返回。 [...]仅与ISO / IEC 9075或其他国际标准中定义的条件一起返回与这些类别相关的子类值,这些类别也以这13个字符之一开头。 [...]与这些类相关联的子类值,以数字“5”,“6”,“7”,“8”或“9”之一或简单的拉丁大写字母“I”之一开头,'J','K','L','M','N','O','P','Q','R','S','T','U',' V','W','X','Y'或'Z'保留用于实现定义的条件,并称为实现定义的子类。

     

以数字'5','6','7','8'或'9'之一开头的类值或其中一个简单的拉丁大写字母'I','J',' K','L','M','N','O','P','Q','R','S','T','U','V','W' ,'X','Y'或'Z'保留用于实现定义的异常条件,并称为实现定义的类。除了'000'之外的所有子类值(这意味着没有子类)与这些类相关联,都是为实现定义的条件保留的,并且被称为实现定义的子类。

(来自SQL:2011第2册)

这些标准类(和标准定义的子类)列在第2册(基础),3(CLI),4(PSM),9(MED),10(OLB),13(JRT)和14(XML)中。它还列出了某些内容是异常,警告,成功完成条件还是无数据完成条件(并非所有SQL状态都是错误!)

例如,您问题中列出的sqlstates是:

  • 08001:class:连接异常,子类:SQL-client无法建立SQL连接
  • 08007:class:连接异常,子类:事务解析未知
  • 08S01:class:连接异常,子类:以S开头,因此是实现定义的子类(在ODBC中定义为通信链接失败)
  • 57P01:class:从5开始,实现定义类也是如此,它似乎是ADMIN SHUTDOWN的PostgreSQL sqlstate
  • HY000:class:特定于CLI的条件(在第3册中定义,CLI),子类:(无子类)

HY000是一个非常通用的错误,因为某些数据库或驱动程序会为没有特定sqlstate的任何错误返回它,因此它通常被视为致命错误。我认为BoneCP的行为将其视为杀死整个连接池的一个原因有点过分,因为HY000也可能因为相对良性的错误而被抛出。其他sqlstates通常表示连接到数据库(0800108S01)或数据库不可用(57P01)或数据库本身存在问题({{ 1}})。

答案 2 :(得分:0)

状态代码说明的链接实际上在您引用的同一代码块中: https://github.com/wwadge/bonecp/blob/master/bonecp/src/main/java/com/jolbox/bonecp/ConnectionHandle.java#L163