JDBC
-一、JDBC連接配接過程
01.注冊驅動
<code>Class.forName(</code><code>"oracle.jdbc.driver.OracleDriver"</code><code>);</code>
02.擷取連接配接
<code>Connection</code> <code>conn = DriverManager.getConnection(</code><code>"jdbc:oracle:thin:@10.0.19.252:1521:orcl"</code><code>,</code><code>"itxy"</code><code>,</code><code>"itxy"</code><code>);</code>
-二、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
表示資料庫結果集的資料表,通常通過執行查詢資料庫的語句生成。
<code> ResultSet</code> 對象具有指向其目前資料行的光标。最初,光标被置于第一行之前。<code>next</code> 方法将光标移動到下一行;因為該方法在 <code>ResultSet</code> 對象沒有下一行時傳回 <code>false</code>,是以可以在 <code>while</code> 循環中使用它來疊代結果集。
預設的 <code>ResultSet</code> 對象不可更新,僅有一個向前移動的光标。是以,隻能疊代它一次,并且隻能按從第一行到最後一行的順序進行。
-三、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
通路資料庫的使用者名或密碼錯誤
注:
JDBC 與
UPDATE 表名 SET 字段名1=表達式1, 字段名2=表達式2, ... WHERE 條件;
重點: 傳回值,int (update語句影響的記錄條數)
但是如果jdbc與insert就不用看傳回值,如果有異常,則表示插入失敗。
異常總結
1. 異常的處理順序,一定是子類異常處理在前,父類異常處理在後
<code>try</code> <code>{</code>
<code> </code><code>biz.deleteStudent(</code><code>"s002"</code><code>); </code>
<code> </code><code>System.out.println(</code><code>"删除完畢!"</code><code>);</code>
<code>} </code><code>catch</code> <code>(SQLIntegrityConstraintViolationException e) {</code>
<code> </code>
<code>} </code><code>catch</code> <code>(Exception e) {</code>
<code> </code><code>e.printStackTrace();</code>
<code> </code><code>System.out.println(</code><code>"系統異常,請檢查"</code><code>);</code>
<code>} </code>
2. 在三層架構中,每層都可能出現異常,但是隻有UI層采用最終的異常顯示的決定權。
其它層可以捕獲異常,但是處理後需要再次抛出!
3. 非托管資源(不受GC管理的資源),一定要在finally中釋放,放在資源洩漏;
不受GC管理的資源:如資料連接配接Connection , 必須要用close()方法釋放
還有IO流的釋放,也必須使用close()
<code> </code><code>try</code> <code>{</code>
<code> </code>
<code>}</code><code>finally</code><code>{</code>
<code> </code><code>dao.closeConnection();</code>
<code>}</code>
4. 自定義異常
<code>public</code> <code>class</code> <code>HavaSonRecordsException </code><code>extends</code> <code>Exception{</code>
<code> </code>
<code> </code><code>public</code> <code>HavaSonRecordsException(String msg){</code>
<code> </code><code>super</code><code>(msg);</code>
<code> </code><code>}</code>
5. java.lang 類 Throwable
直接已知子類:
Error, Exception
Error 是 Throwable 的子類,用于訓示合理的應用程式不應該試圖捕獲的嚴重問題。
注意: Error無需用try catch
Error異常舉例: 如記憶體越界、記憶體溢出
6. try catch 是可以嵌套使用的
7.隻有try,沒有catch
<code> </code><code>try</code> <code>{</code>
<code> </code><code>dao.updateStuState(</code><code>0</code><code>, sno); </code>
<code> </code><code>//釋放IO流的句柄</code>
<code> </code><code>System.out.println(</code><code>"io資源釋放"</code><code>);</code>
8. checked Exception 與 unChecked Exception(Runtime Exception)
checked Exception(特點:在編譯期可以明确異常的可能發生的位置,而且必須要捕獲它):
ClassNotFoundException
SQLException
Runtime Excepiton (編譯期無法檢查到這個異常,隻有在程式運作期間才能知道):
NullExcepiton , 10/0 , format("")
<code>public</code> <code>class</code> <code>InputNullExcepiton </code><code>extends</code> <code>RuntimeException{} </code><code>//RuntimeException無需強制處理</code>
<code>public</code> <code>class</code> <code>InputNullExcepiton </code><code>extends</code> <code>Exception{} </code><code>//自定義異常,建議extends Exception</code>
//資料庫Connection是一種寶貴的資源,很容易稱為業務系統的性能瓶頸
使用原則:
晚打開,早關閉 ----- 使用時間越短越好
Connection盡量可以重用
//資料庫Connection的數量不是無限的,它受限于硬體(CPU)
補:
java.util 類 Date //除了dao層之外,都盡量使用java.util.Date
java.sql 類 Date //隻能在dao層使用
練習(Java項目):
自定義異常
<code>public</code> <code>class</code> <code>InputNullException </code><code>extends</code> <code>Exception {</code>
<code> </code><code>public</code> <code>InputNullException(String msg){</code>
web層
<code>public</code> <code>class</code> <code>StuUI {</code>
<code> </code><code>/**</code>
<code> </code><code>* 删除學生</code>
<code> </code><code>*/</code>
<code> </code><code>public</code> <code>static</code> <code>void</code> <code>deleteStuTest(){</code>
<code> </code><code>StuBiz biz = </code><code>new</code> <code>StuBiz();</code>
<code> </code><code>try</code> <code>{</code>
<code> </code><code>biz.deleteStudent(</code><code>"s003234"</code><code>); </code>
<code> </code><code>System.out.println(</code><code>"删除完畢!"</code><code>);</code>
<code> </code><code>} </code><code>catch</code> <code>(Exception e) {</code>
<code> </code><code>e.printStackTrace();</code>
<code> </code><code>System.out.println(</code><code>"系統異常,請檢查"</code><code>);</code>
<code> </code><code>} </code>
<code> </code><code>* 添加學生</code>
<code> </code><code>public</code> <code>static</code> <code>void</code> <code>addStuTest(){</code>
<code> </code><code>TStudent ts = </code><code>new</code> <code>TStudent();</code>
<code> </code>
<code> </code><code>ts.setSname(</code><code>"jack"</code><code>);</code>
<code> </code><code>ts.setSno(</code><code>"s002244"</code><code>);</code>
<code> </code><code>ts.setCno(</code><code>"c0124"</code><code>);</code>
<code> </code><code>ts.setSex(</code><code>"f"</code><code>);</code>
<code> </code><code>ts.setAddress(</code><code>"taiyuan"</code><code>);</code>
<code> </code><code>ts.setTel(</code><code>"155345263"</code><code>);</code>
<code> </code><code>String s = </code><code>"2012-06-21"</code><code>;</code>
<code> </code><code>SimpleDateFormat sdf = </code><code>new</code> <code>SimpleDateFormat(</code><code>"yyyy-MM-dd"</code><code>);</code>
<code> </code><code>java.util.Date d1 = </code><code>null</code><code>;</code>
<code> </code><code>d1 = sdf.parse(s);</code>
<code> </code><code>} </code><code>catch</code> <code>(ParseException e1) {</code>
<code> </code><code>e1.printStackTrace();</code>
<code> </code><code>} </code><code>//先把字元串轉為util.Date對象</code>
<code> </code><code>java.sql.Date d2 = </code><code>new</code> <code>java.sql.Date(d1.getTime()); </code>
<code> </code><code>ts.setBirthday(d2);</code>
<code> </code><code>ts.setHeight(</code><code>54</code><code>);</code>
<code> </code><code>ts.setState(</code><code>1</code><code>);</code>
<code> </code><code>biz.addStu(ts);</code>
<code> </code><code>System.out.println(</code><code>"添加學生成功!"</code><code>);</code>
<code> </code><code>} </code><code>catch</code><code>(InputNullException e){</code>
<code> </code><code>System.out.println(</code><code>"入參為空!"</code><code>);</code>
<code> </code><code>}</code><code>catch</code> <code>(Exception e) {</code>
<code> </code><code>System.out.println(</code><code>"插入失敗!"</code><code>);</code>
<code> </code><code>}</code>
<code> </code><code>* 查詢所有學生資訊</code>
<code> </code><code>public</code> <code>static</code> <code>void</code> <code>showStu(){</code>
<code> </code><code>List<TStudent> stus = biz.findAllStu();</code>
<code> </code><code>Iterator<TStudent> it = stus.iterator();</code>
<code> </code><code>while</code><code>(it.hasNext()){</code>
<code> </code><code>TStudent t = it.next();</code>
<code> </code><code>System.out.println(t.getSname() + </code><code>"--"</code> <code>+ t.getSno() + </code><code>"--"</code> <code>+ t.getBirthday());</code>
<code> </code><code>}</code>
<code> </code><code>System.out.println(</code><code>"查詢失敗!"</code><code>);</code>
<code> </code><code>public</code> <code>static</code> <code>void</code> <code>main(String[] args) {</code>
<code> </code><code>StuUI.showStu();</code>
業務邏輯層:
<code>public</code> <code>class</code> <code>StuBiz {</code>
<code> </code><code>* 注意: 1. 當學生沒有産生業務資料時,直接删除實體記錄</code>
<code> </code><code>* 2. 當學生産生了業務資料時,隻能做邏輯删除</code>
<code> </code><code>* @param sno</code>
<code> </code><code>* @throws Exception</code>
<code> </code><code>public</code> <code>void</code> <code>deleteStudent(String sno) </code><code>throws</code> <code>Exception{</code>
<code> </code><code>if</code><code>(sno != </code><code>null</code><code>){</code>
<code> </code><code>StuDao dao = </code><code>new</code> <code>StuDao();</code>
<code> </code><code>try</code> <code>{</code>
<code> </code><code>dao.deleteStudent(sno);</code>
<code> </code><code>}</code><code>catch</code><code>(java.sql.SQLIntegrityConstraintViolationException e){</code>
<code> </code><code>if</code><code>(e.getSQLState().equals(</code><code>"23000"</code><code>)){</code>
<code> </code><code>//找到了子記錄</code>
<code> </code><code>try</code> <code>{</code>
<code> </code><code>dao.updateStuState(</code><code>0</code><code>, sno);</code>
<code> </code><code>} </code><code>catch</code> <code>(Exception e2) {</code>
<code> </code><code>e2.printStackTrace();</code>
<code> </code><code>throw</code> <code>e2;</code>
<code> </code><code>}</code><code>finally</code><code>{</code>
<code> </code><code>dao.closeConnection();</code>
<code> </code><code>} </code>
<code> </code><code>}</code>
<code> </code><code>} </code><code>catch</code> <code>(Exception e) { </code>
<code> </code><code>throw</code> <code>e;</code>
<code> </code><code>}</code><code>finally</code><code>{</code>
<code> </code><code>dao.closeConnection();</code>
<code> </code>
<code> </code><code>}</code><code>else</code><code>{</code>
<code> </code><code>throw</code> <code>new</code> <code>Exception(</code><code>"入參錯誤,sno=null"</code><code>);</code>
<code> </code><code>* @param ts</code>
<code> </code><code>public</code> <code>void</code> <code>addStu(TStudent ts) </code><code>throws</code> <code>Exception{</code>
<code> </code><code>if</code><code>(ts!=</code><code>null</code><code>){</code>
<code> </code><code>boolean</code> <code>bet = dao.findClass(ts.getCno());</code>
<code> </code><code>if</code><code>(!bet){</code>
<code> </code><code>throw</code> <code>new</code> <code>Exception(</code><code>"班級不存在"</code><code>);</code>
<code> </code><code>}</code><code>else</code><code>{</code>
<code> </code><code>dao.addStu(ts);</code>
<code> </code><code>}</code>
<code> </code><code>} </code><code>catch</code> <code>(Exception e) {</code>
<code> </code><code>}</code><code>finally</code> <code>{</code>
<code> </code><code>} </code>
<code> </code><code>throw</code> <code>new</code> <code>Exception(</code><code>"入參錯誤!"</code><code>);</code>
<code> </code><code>* @return</code>
<code> </code><code>public</code> <code>List<TStudent> findAllStu() </code><code>throws</code> <code>Exception {</code>
<code> </code><code>//注意:面向接口程式設計不能是實作類傳回</code>
<code> </code><code>List<TStudent> stus;</code>
<code> </code><code>StuDao dao = </code><code>new</code> <code>StuDao();</code>
<code> </code><code>stus = dao.findAllStu();</code>
<code> </code><code>throw</code> <code>e;</code>
<code> </code><code>}</code><code>finally</code> <code>{</code>
<code> </code><code>dao.closeConnection();</code>
<code> </code><code>return</code> <code>stus;</code>
資料層:
<code>public</code> <code>class</code> <code>StuDao </code><code>extends</code> <code>BaseDao{</code>
<code> </code><code>public</code> <code>void</code> <code>deleteStudent(String sno) </code><code>throws</code> <code>Exception{ </code>
<code> </code><code>String sql = </code><code>"delete from tstudent where sno=?"</code><code>;</code>
<code> </code><code>this</code><code>.openConnection();</code>
<code> </code><code>PreparedStatement ps = </code><code>this</code><code>.conn.prepareStatement(sql);</code>
<code> </code><code>ps.setString(</code><code>1</code><code>, sno);</code>
<code> </code><code>ps.executeUpdate();</code>
<code> </code><code>ps.close(); </code>
<code> </code><code>* 修改學生的狀态值</code>
<code> </code><code>* @param state</code>
<code> </code><code>public</code> <code>void</code> <code>updateStuState(</code><code>int</code> <code>state,String sno) </code><code>throws</code> <code>Exception{</code>
<code> </code><code>String sql = </code><code>"update tstudent set state=? where sno=?"</code><code>;</code>
<code> </code><code>ps.setInt(</code><code>1</code><code>, state);</code>
<code> </code><code>ps.setString(</code><code>2</code><code>, sno);</code>
<code> </code><code>ps.close();</code>
<code> </code><code>public</code> <code>void</code> <code>addStu(TStudent ts) </code><code>throws</code> <code>Exception {</code>
<code> </code><code>String sql = </code><code>"insert into tstudent values(?,?,?,?,?,?,?,?,?)"</code><code>;</code>
<code> </code><code>//資料庫打開</code>
<code> </code><code>ps.setString(</code><code>1</code><code>, ts.getSname());</code>
<code> </code><code>ps.setString(</code><code>2</code><code>, ts.getSno());</code>
<code> </code><code>ps.setString(</code><code>3</code><code>, ts.getCno());</code>
<code> </code><code>ps.setString(</code><code>4</code><code>, ts.getSex());</code>
<code> </code><code>ps.setString(</code><code>5</code><code>, ts.getAddress());</code>
<code> </code><code>ps.setString(</code><code>6</code><code>, ts.getTel());</code>
<code> </code><code>ps.setDate(</code><code>7</code><code>, ts.getBirthday());</code>
<code> </code><code>ps.setInt(</code><code>8</code><code>, ts.getHeight());</code>
<code> </code><code>ps.setInt(</code><code>9</code><code>, ts.getState());</code>
<code> </code>
<code> </code><code>* 添加學生的時候,檢查班級是否存在</code>
<code> </code><code>* @param cno</code>
<code> </code><code>public</code> <code>boolean</code> <code>findClass(String cno) </code><code>throws</code> <code>Exception {</code>
<code> </code><code>boolean</code> <code>bRet = </code><code>false</code><code>;</code>
<code> </code><code>String sql = </code><code>"select * from tclass where cno=?"</code><code>;</code>
<code> </code><code>ps.setString(</code><code>1</code><code>, cno);</code>
<code> </code><code>ResultSet rs = ps.executeQuery();</code>
<code> </code><code>while</code><code>(rs.next()){</code>
<code> </code><code>bRet = </code><code>true</code><code>;</code>
<code> </code><code>rs.close();</code>
<code> </code><code>return</code> <code>bRet;</code>
<code> </code><code>List<TStudent> stuList;</code><code>//寫成兩行</code>
<code> </code><code>String sql = </code><code>"select * from tstudent"</code><code>;</code><code>//寫在openConnection之前</code>
<code> </code><code>stuList = </code><code>new</code> <code>ArrayList<TStudent>();</code><code>//這樣如果前面有錯就不用産生記憶體配置設定</code>
<code> </code><code>TStudent ts = </code><code>new</code> <code>TStudent();</code><code>//new TStudent()是建立一個記憶體,這個不會被釋放掉,隻不過每次會建立對象引用</code>
<code> </code><code>ts.setSname(rs.getString(</code><code>"sname"</code><code>));</code>
<code> </code><code>ts.setCno(rs.getString(</code><code>"cno"</code><code>));</code>
<code> </code><code>ts.setSno(rs.getString(</code><code>"sno"</code><code>));</code>
<code> </code><code>ts.setAddress(rs.getString(</code><code>"address"</code><code>));</code>
<code> </code><code>ts.setSex(rs.getString(</code><code>"sex"</code><code>));</code>
<code> </code><code>ts.setTel(rs.getString(</code><code>"tel"</code><code>));</code>
<code> </code><code>ts.setBirthday(rs.getDate(</code><code>"birthday"</code><code>));</code>
<code> </code><code>ts.setHeight(rs.getInt(</code><code>"height"</code><code>));</code>
<code> </code><code>ts.setState(rs.getInt(</code><code>"state"</code><code>));</code>
<code> </code><code>stuList.add(ts);</code><code>//集合裡面放的是引用,向集合中添加,就是複制對象位址,然後釋放這個對象位址</code>
<code> </code><code>return</code> <code>stuList;</code>
basedao
<code>public</code> <code>class</code> <code>BaseDao {</code>
<code> </code><code>protected</code> <code>Connection conn; </code>
<code> </code><code>public</code> <code>void</code> <code>openConnection() </code><code>throws</code> <code>Exception{</code>
<code> </code><code>//通過反射技術,對oracel的驅動對象進行類的加載 (其實是在做類型檢查)</code>
<code> </code><code>//在類的加載時,會調用OracleDriver中的靜态代碼塊和靜态變量初始化</code>
<code> </code><code>Class.forName(</code><code>"oracle.jdbc.driver.OracleDriver"</code><code>); </code>
<code> </code><code>conn = DriverManager.getConnection(</code><code>"jdbc:oracle:thin:@10.0.19.252:1521:orcl"</code><code>,</code><code>"itxy"</code><code>,</code><code>"itxy"</code><code>);</code>
<code> </code><code>public</code> <code>void</code> <code>closeConnection() {</code>
<code> </code><code>if</code><code>(</code><code>this</code><code>.conn != </code><code>null</code><code>){</code>
<code> </code><code>this</code><code>.conn.close(); </code>
<code> </code><code>e.printStackTrace();</code>
版權聲明:原創作品,謝絕轉載。否則将追究法律責任
本文轉自 叫我北北 51CTO部落格,原文連結:http://blog.51cto.com/qinbin/1965567