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 { //1、注冊驅動 Class.forName("com.mysql.jdbc.Driver"); //數據庫連接所需參數 String user = "root"; String password = "123456"; String url = "jdbc:mysql://localhost:3306/sampledb?useUnicode=true&characterEncoding=utf-8"; //2、獲取連接對象 Connection conn = DriverManager.getConnection(url, user, password); //設置sql語句 String sql = "select * from student"; //3、獲得sql語句執行對象 Statement stmt = conn.createStatement(); //4、執行sql並保存結果集 ResultSet rs = stmt.executeQuery(sql); //5、處理結果集 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)); } //6、資源關閉 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 { //1、注冊驅動 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 { //2、獲取連接對象 conn = DriverManager.getConnection(url, user, password); //3、設置sql語句 String sql = "select * from student"; //4、獲得sql語句執行對象 stmt = conn.createStatement(); //5、執行並保存結果集 rs = stmt.executeQuery(sql); //6、處理結果集 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 { //7、資源關閉 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); } }
原文地址:
JDBC 異常簡介 jDBC簡介(六)