【JDBC4.2】JDBC中的Exception

JDBC中的异常类包括SQLException类和它的子类们。

1.SQLException

SQLException包含下面信息:

信息项获取方法备注
错误描述SQLException#getMessage
SQLStateSQLException#getSQLState
error codeSQLException#getMessage
causeSQLException#getCause递归获取一个异常上的Throwable
多个异常SQLException#getNextException递归如果已经没有异常,返回null

对Chained Execeptions的支持

chained exceptions :异常链或链式异常
在java代码中常常会再捕获一个异常后抛出另外一个异常,并且希望把异常原始信息保存下来,这被称为异常链
JDK1.4以后,所有Throwable的子类子构造器中都可以接受一个cause对象作为参数,这个cause就异常原由,代表着原始异常,即使在当前位置创建并抛出行的异常,也可以通过这个cause追踪到异常最初发生的位置。比如:throw new RuntimeException("ex---2",e1); 把e1加载到另一个异常的异常链上。

SQLException对异常链的支持包括:
1.增加了构造函数支持cause Throwable参数
2.可以使用ForEach循环获取所有Cause(代替每次getNextException后调用getCause)
3.getCause可能返回一个非SQLException的Exception

定位SQLExceptions的代码

在执行SQL的时候,可能会出现多个Exception,每个Exception都有它们自己的Cause。可以递归使用getNextException获取所有的Exception,每次获取Exception时候再递归调用getCause获取所有Cause Throwable。

try{
  //...
}catch(SQLException ex) {
  while(ex != null) {
    System.out.println("SQLState:" + ex.getSQLState());
    System.out.println("Error Code:" + ex.getErrorCode());
    System.out.println("Message:" + ex.getMessage());
    Throwable t = ex.getCause();
    while(t != null) {
        System.out.println("Cause:" + t);
        t = t.getCause();
    }
    ex = ex.getNextException();
  }
}

使用ForEach直接获取所有Cause Throwable

try{
  //...
}catch(SQLException ex) {
  for(Throwable e : ex ) {
    System.out.println("Error encountered: " + e);
  }
}

2.SQLWarning

SQLWarning是SQLException的子类,下面这些接口的实现类的getWarnings方法会生成SQLWarning
■ Connection
■ DataSet
■ Statement
■ ResultSet
如果出现多个SQLWarning,他们会被串联到第一个SQLWarning上,通过getNextWarning方法递归地获取所有SQLWarning

3.DataTruncation数据截断

DataTruncation是SQLWarning的子类,当数据库中的数据被截断时,会生成此对象。比如:
数据库中student表的name是varchar(5),当我保存超过五个字符。

Connection connection = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/test?serverTimezone=UTC",
                "root",
                "123456");

Statement statement = connection.createStatement();
int rows = statement.executeUpdate("INSERT INTO student(name,age) VALUES ('TooLongName',19)");

会抛出如下异常:

try{
        Connection connection = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/test?serverTimezone=UTC",
                    "root",
                    "123456");

        Statement statement = connection.createStatement();
        int rows = statement.executeUpdate("INSERT INTO student(name,age) VALUES ('TooLongName',19)");
        statement.close();
        connection.close();
    }catch (DataTruncation e){
        System.out.println(e.getSQLState());//22001为写入,01004为读取
        System.out.println(e.getMessage());
        System.out.println(e.getParameter());
        //...其他方法
}

5.BatchUpdateException

批量更新(BatchUpdate)产生的异常。

6.分类的异常Categorized SQLExceptions

这些异常可以和特定的 SQLStates相关:
■ SQLNonTransientException
■ SQLTransientException
■ SQLRecoverableException

NonTransient SQLExceptions

通常是由代码错误引起的,重试后任然会执行失败。异常出现时,Connection仍然有效。
包含SQLFeatureNotSupportedException,SQLNonTransientConnectionException,SQLDataException,SQLIntegrityConstraintViolationException,SQLInvalidAuthorizationException,SQLSyntaxErrorException等

SQLTransientException

通常不是由代码错误引起的,重新执行后可能会成功。异常出现时,Connection仍然有效。
包括SQLTransientConnectionException,SQLTransactionRollbackException,SQLTimeoutException等。

SQLRecoverableException

需要关闭Connection,重新建立。异常出现时,Connection不再有效。

7.SQLClientinfoException

该异常由Connection.setClientInfo引发。