JDBC和異常總結及常見使用
JDBC
-一、JDBC連接過程
01.註冊驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
02.獲取連接
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@10.0.19.252:1521:orcl","itxy","itxy");
-二、JDBC 常用接口
JDBC : sun提供的訪問數據庫的規範
這套規範用於高速數據庫廠商,通過何種方式訪問他們的數據庫
01.java.sql 接口 Connection
sun的JDBC是一套接口規範,沒有提供實現 (JDBC的接口實現,只能由各個數據庫廠商自己實現)
02.java.sql
接口 Statement 用於執行靜態 SQL 語句並返回它所生成結果的對象。
java.sql
接口 PreparedStatement 表示預編譯的 SQL 語句的對象。
註意:開發的時候首先 PreparedStatement
原因: 1. 預編譯的 SQL 語句的對象運行速度快
2. 安全 (可以防止SQL註入攻擊)
03.java.sql 接口 ResultSet
表示數據庫結果集的數據表,通常通過執行查詢數據庫的語句生成。
ResultSet
對象具有指向其當前數據行的光標。最初,光標被置於第一行之前。next
ResultSet
對象沒有下一行時返回 false
,所以可以在
while
循環中使用它來叠代結果集。 默認的 ResultSet
對象不可更新,僅有一個向前移動的光標。因此,只能叠代它一次,並且只能按從第一行到最後一行的順序進行。
-三、JDBC使用常見異常
java.lang
類 Class<T>
java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver2
數據庫驅動未加載成功
java.sql.SQLException: The Network Adapter could not establish the connection
數據庫連接串配置錯誤
java.sql.SQLException: ORA-01017: invalid username/password; logon denied
訪問數據庫的用戶名或密碼錯誤
異常總結
1. 異常的處理順序,一定是子類異常處理在前,父類異常處理在後
try { biz.deleteStudent("s002"); System.out.println("刪除完畢!"); } catch (SQLIntegrityConstraintViolationException e) { } catch (Exception e) { e.printStackTrace(); System.out.println("系統異常,請檢查"); }
2. 在三層架構中,每層都可能出現異常,但是只有UI層采用最終的異常顯示的決定權。
其它層可以捕獲異常,但是處理後需要再次拋出!
3. 非托管資源(不受GC管理的資源),一定要在finally中釋放,放在資源泄漏;
不受GC管理的資源:如數據連接Connection , 必須要用close()方法釋放
還有IO流的釋放,也必須使用close()
try { }finally{ dao.closeConnection(); }
4. 自定義異常
public class HavaSonRecordsException extends Exception{ public HavaSonRecordsException(String msg){ super(msg); } }
5. java.lang 類 Throwable
直接已知子類:
Error, Exception
Error 是 Throwable 的子類,用於指示合理的應用程序不應該試圖捕獲的嚴重問題。
註意: Error無需用try catch
Error異常舉例: 如內存越界、內存溢出
6. try catch 是可以嵌套使用的
7.只有try,沒有catch
try { dao.updateStuState(0, sno); }finally{ //釋放IO流的句柄 System.out.println("io資源釋放"); }
8. checked Exception 與 unChecked Exception(Runtime Exception)
checked Exception(特點:在編譯期可以明確異常的可能發生的位置,而且必須要捕獲它):
ClassNotFoundException
SQLException
Runtime Excepiton (編譯期無法檢查到這個異常,只有在程序運行期間才能知道):
NullExcepiton , 10/0 , format("")
public class InputNullExcepiton extends RuntimeException{} //RuntimeException無需強制處理 public class InputNullExcepiton extends Exception{} //自定義異常,建議extends Exception
//數據庫Connection是一種寶貴的資源,很容易稱為業務系統的性能瓶頸
使用原則:
晚打開,早關閉 ----- 使用時間越短越好
Connection盡量可以重用
//數據庫Connection的數量不是無限的,它受限於硬件(CPU)
補:
java.util 類 Date //除了dao層之外,都盡量使用java.util.Date
java.sql 類 Date //只能在dao層使用
練習(Java項目):
自定義異常
public class InputNullException extends Exception { public InputNullException(String msg){ super(msg); } }
web層
public class StuUI { /** * 刪除學生 */ public static void deleteStuTest(){ StuBiz biz = new StuBiz(); try { biz.deleteStudent("s003234"); System.out.println("刪除完畢!"); } catch (Exception e) { e.printStackTrace(); System.out.println("系統異常,請檢查"); } } /** * 添加學生 */ public static void addStuTest(){ StuBiz biz = new StuBiz(); TStudent ts = new TStudent(); ts.setSname("jack"); ts.setSno("s002244"); ts.setCno("c0124"); ts.setSex("f"); ts.setAddress("taiyuan"); ts.setTel("155345263"); String s = "2012-06-21"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); java.util.Date d1 = null; try { d1 = sdf.parse(s); } catch (ParseException e1) { e1.printStackTrace(); } //先把字符串轉為util.Date對象 java.sql.Date d2 = new java.sql.Date(d1.getTime()); ts.setBirthday(d2); ts.setHeight(54); ts.setState(1); try { biz.addStu(ts); System.out.println("添加學生成功!"); } catch(InputNullException e){ System.out.println("入參為空!"); }catch (Exception e) { e.printStackTrace(); System.out.println("插入失敗!"); } } /** * 查詢所有學生信息 */ public static void showStu(){ StuBiz biz = new StuBiz(); try { List<TStudent> stus = biz.findAllStu(); Iterator<TStudent> it = stus.iterator(); while(it.hasNext()){ TStudent t = it.next(); System.out.println(t.getSname() + "--" + t.getSno() + "--" + t.getBirthday()); } } catch (Exception e) { e.printStackTrace(); System.out.println("查詢失敗!"); } } public static void main(String[] args) { StuUI.showStu(); } }
業務邏輯層:
public class StuBiz { /** * 刪除學生 * 註意: 1. 當學生沒有產生業務數據時,直接刪除物理記錄 * 2. 當學生產生了業務數據時,只能做邏輯刪除 * @param sno * @throws Exception */ public void deleteStudent(String sno) throws Exception{ if(sno != null){ StuDao dao = new StuDao(); try { dao.deleteStudent(sno); }catch(java.sql.SQLIntegrityConstraintViolationException e){ if(e.getSQLState().equals("23000")){ //找到了子記錄 try { dao.updateStuState(0, sno); } catch (Exception e2) { e2.printStackTrace(); throw e2; }finally{ dao.closeConnection(); } } } catch (Exception e) { throw e; }finally{ dao.closeConnection(); } }else{ throw new Exception("入參錯誤,sno=null"); } } /** * 添加學生 * @param ts * @throws Exception */ public void addStu(TStudent ts) throws Exception{ if(ts!=null){ StuDao dao = new StuDao(); try { boolean bet = dao.findClass(ts.getCno()); if(!bet){ throw new Exception("班級不存在"); }else{ dao.addStu(ts); } } catch (Exception e) { throw e; }finally { dao.closeConnection(); } }else{ throw new Exception("入參錯誤!"); } } /** * 查詢所有學生信息 * @return * @throws Exception */ public List<TStudent> findAllStu() throws Exception { //註意:面向接口編程不能是實現類返回 List<TStudent> stus; StuDao dao = new StuDao(); try { stus = dao.findAllStu(); } catch (Exception e) { throw e; }finally { dao.closeConnection(); } return stus; } }
數據層:
public class StuDao extends BaseDao{ /** * 刪除學生 * 註意: 1. 當學生沒有產生業務數據時,直接刪除物理記錄 * 2. 當學生產生了業務數據時,只能做邏輯刪除 * @param sno * @throws Exception */ public void deleteStudent(String sno) throws Exception{ String sql = "delete from tstudent where sno=?"; this.openConnection(); PreparedStatement ps = this.conn.prepareStatement(sql); ps.setString(1, sno); ps.executeUpdate(); ps.close(); } /** * 修改學生的狀態值 * @param state * @throws Exception */ public void updateStuState(int state,String sno) throws Exception{ String sql = "update tstudent set state=? where sno=?"; this.openConnection(); PreparedStatement ps = this.conn.prepareStatement(sql); ps.setInt(1, state); ps.setString(2, sno); ps.executeUpdate(); ps.close(); } /** * 添加學生 * @param ts * @throws Exception */ public void addStu(TStudent ts) throws Exception { String sql = "insert into tstudent values(?,?,?,?,?,?,?,?,?)"; //數據庫打開 this.openConnection(); PreparedStatement ps = this.conn.prepareStatement(sql); ps.setString(1, ts.getSname()); ps.setString(2, ts.getSno()); ps.setString(3, ts.getCno()); ps.setString(4, ts.getSex()); ps.setString(5, ts.getAddress()); ps.setString(6, ts.getTel()); ps.setDate(7, ts.getBirthday()); ps.setInt(8, ts.getHeight()); ps.setInt(9, ts.getState()); ps.executeUpdate(); ps.close(); } /** * 添加學生的時候,檢查班級是否存在 * @param cno * @return * @throws Exception */ public boolean findClass(String cno) throws Exception { boolean bRet = false; String sql = "select * from tclass where cno=?"; this.openConnection(); PreparedStatement ps = this.conn.prepareStatement(sql); ps.setString(1, cno); ResultSet rs = ps.executeQuery(); while(rs.next()){ bRet = true; } rs.close(); ps.close(); return bRet; } /** * 查詢所有學生信息 * @return * @throws Exception */ public List<TStudent> findAllStu() throws Exception { List<TStudent> stuList;//寫成兩行 String sql = "select * from tstudent";//寫在openConnection之前 this.openConnection(); PreparedStatement ps = this.conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(); stuList = new ArrayList<TStudent>();//這樣如果前面有錯就不用產生內存分配 while(rs.next()){ TStudent ts = new TStudent();//new TStudent()是新建一個內存,這個不會被釋放掉,只不過每次會建立對象引用 ts.setSname(rs.getString("sname")); ts.setCno(rs.getString("cno")); ts.setSno(rs.getString("sno")); ts.setAddress(rs.getString("address")); ts.setSex(rs.getString("sex")); ts.setTel(rs.getString("tel")); ts.setBirthday(rs.getDate("birthday")); ts.setHeight(rs.getInt("height")); ts.setState(rs.getInt("state")); stuList.add(ts);//集合裏面放的是引用,向集合中添加,就是復制對象地址,然後釋放這個對象地址 } rs.close(); ps.close(); return stuList; } }
basedao
public class BaseDao { protected Connection conn; public void openConnection() throws Exception{ //通過反射技術,對oracel的驅動對象進行類的加載 (其實是在做類型檢查) //在類的加載時,會調用OracleDriver中的靜態代碼塊和靜態變量初始化 Class.forName("oracle.jdbc.driver.OracleDriver"); conn = DriverManager.getConnection("jdbc:oracle:thin:@10.0.19.252:1521:orcl","itxy","itxy"); } public void closeConnection() { if(this.conn != null){ try { this.conn.close(); } catch (Exception e) { e.printStackTrace(); } } } }
本文出自 “秦斌的博客” 博客,謝絕轉載!
JDBC和異常總結及常見使用