JDBC 異常簡介 jDBC簡介(六)

SQL 異常簡介

對於數據庫的操做訪問,必然也極可能拋出異常
JDBC中定義了SQLException,用於描述數據庫相關操做中可能出現的異常狀況。
java.sql.SQLException 
 
異常本質沒有什麼特別的邏輯,一般藉助於異常的名稱傳達異常的類型,經過攜帶的信息進行進一步分析
SQLException是SQL相關的異常的始祖 ,主要有如下擴展:
  • BatchUpdateException
  • RowSetWarning
  • SerialException
  • SQLClientInfoException
  • SQLNonTransientException
  • SQLRecoverableException
  • SQLTransientException
  • SQLWarning
  • SyncFactoryException
  • SyncProviderException 
每一個 SQLException 均可提供如下多種消息:
特定於每一個供應商的整數錯誤代碼 。一般,這將是底層數據庫返回的實際錯誤代碼。
描述錯誤的字符串 。此字符串用做 Java Exception 消息,能夠經過方法 getMessage 得到(繼承來的方法)。
"SQLstate" 字符串 ,該字符串遵照 XOPEN SQLstate 約定或 SQL:2003 約定。SQLState 字符串的值在適當的規範中描述。DatabaseMetaData 的方法 getSQLStateType 可用於肯定驅動程序返回 XOPEN 類型仍是 SQL:2003 類型。
到下一個 Exception 的連接可使用此連接提供其餘錯誤信息。
因果關係,若是存在任何致使此 SQLException 的緣由。 

方法列表以下:

int getErrorCode()
          獲取此 SQLException 對象的特定於供應商的異常代碼。
String getSQLState()
          獲取此 SQLException 對象的 SQLState。
Iterator<Throwable> iterator()
          返回在連接的 SQLExceptions 上進行迭代的迭代器。
void setNextException(SQLException ex)
          將 SQLException 對象添加到連接的末尾。
SQLException getNextException()
          經過 setNextException(SQLException ex) 獲取連接到此 SQLException 對象的異常

異常處理

下面是第一個JDBC示例中的代碼,沒有很好地處理異常,直接throws Exception了
package jdbc.jdbc;


import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.Statement;


/**

* 第一個JDBC

* @author noteless

*/

public class FirstJDBC {

public static void main(String[] args) throws Exception {

//一、註冊驅動

Class.forName("com.mysql.jdbc.Driver");

//數據庫鏈接所需參數

String user = "root";

String password = "123456";

String url = "jdbc:mysql://localhost:3306/sampledb?useUnicode=true&characterEncoding=utf-8";

//二、獲取鏈接對象

Connection conn = DriverManager.getConnection(url, user, password);

//設置sql語句

String sql = "select * from student";

//三、得到sql語句執行對象

Statement stmt = conn.createStatement();

//四、執行sql並保存結果集

ResultSet rs = stmt.executeQuery(sql);

//五、處理結果集

while (rs.next()) {

System.out.print("id:" + rs.getInt(1));

System.out.print(",姓名:" + rs.getString(2));

System.out.print(",年齡:" + rs.getInt(3));

System.out.println(",性別:" + rs.getString(4));

}

//六、資源關閉

rs.close();

stmt.close();

conn.close();

}

}

 

對於可能拋出異常的代碼,應該使用try包裹
無論如何,資源最終都應該被關閉,可是若是資源在打開前就出現異常,直接關閉可能會出現問題
並且在資源關閉過程當中也可能出現異常
一個稍微規範一點的形式可能以下所示
package jdbc;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

public class FirstJDBCFormal {

public static void main(String[] args) throws Exception {


//一、註冊驅動

Class.forName("com.mysql.jdbc.Driver");


//數據庫鏈接所需參數

String user = "root";

String password = "123456";

String url = "jdbc:mysql://localhost:3306/sampledb?useUnicode=true&characterEncoding=utf-8";

Connection conn = null;

Statement stmt = null;

ResultSet rs = null;

try {

//二、獲取鏈接對象

conn = DriverManager.getConnection(url, user, password);


//三、設置sql語句

String sql = "select * from student";


//四、得到sql語句執行對象

stmt = conn.createStatement();



//五、執行並保存結果集

rs = stmt.executeQuery(sql);



//六、處理結果集

while (rs.next()) {

System.out.print("id:" + rs.getInt(1));

System.out.print(",姓名:" + rs.getString(2));

System.out.print(",年齡:" + rs.getInt(3));

System.out.println(",性別:" + rs.getString(4));

}

} catch (Exception e) {

throw new RuntimeException(e);

} finally {

//七、資源關閉

try {

if (conn != null) {

conn.close();

}

if (rs != null) {

rs.close();

}

if (stmt != null) {

stmt.close();

}
} catch (SQLException e) {

}
}
}
}

 

最後一塊的finally也能夠處理成下面這種形式
if (conn != null) {

try{

conn.close();

}catch (SQLException e){


}

}

if (rs != null) {

try{

rs.close();

}catch (SQLException e){


}

}

if (stmt != null) {

try{

stmt.close();

}catch (SQLException e){

}

}

 

注意:
catch()後面都應該作些處理的,上面的示例中也省略了

總結

對於JDBC中的異常,咱們重點在於要認識常見的異常,以及出現異常的緣由,可以經過異常信息獲得對問題有一個基本的定位
如今藉助於各類框架工具,根本就不須要手動編寫JDBC程序,更別說本身處理JDBC中的異常了
可是,藉助於框架底層的一些異常仍舊是根源於JDBC,因此須要對JDBC中的異常有一個簡單瞭解,以及如何使用
 
在執行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);

}

}