9.2? JDBC API 2.0 簡(jiǎn)介
9.2.1? 新的記錄集接口(ResultSet接口)
1 新定義了若干個(gè)常數(shù)
這些常數(shù)用于指定ResultSet的類型 游標(biāo)移動(dòng)的方向等性質(zhì) 如下所示?
public static final int FETCH_FORWARD;
public static final int FETCH_REVERSE;
public static final int FETCH_UNKNOWN;
public static final int TYPE_FORWARD_ONLY;
public static final int TYPE_SCROLL_INSENSITIVE;
public static final int TYPE_SCROLL_SENSITIVE;
public static final int CONCUR_READ_ONLY;
public static final int CONCUR_UPDATABLE;
FETCH_FORWORD 該常數(shù)的作用是指定處理記錄集中行的順序是由前到后 即從第一行開始處理 一直到最后一行?
FETCH_REVERSE 該常數(shù)的作用是指定處理記錄集中行的順序是由后到前 即從后一行開始處理 一直到第一行?
FETCH_UNKNOWN 該常數(shù)的作用是不指定處理記錄集中行的順序 由 JDBC 驅(qū)動(dòng)程序和數(shù)據(jù)庫系統(tǒng)決定?
TYPE_FORWARD_ONLY 該常數(shù)的作用是指定數(shù)據(jù)庫游標(biāo)的移動(dòng)方向是向前 不允許向后移動(dòng) 即只能使用ResultSet接口的next()方法 而不能使用 previous()方法 否則會(huì)產(chǎn)生錯(cuò)誤?
TYPE_SCROLL_INSENSITIVE 該常數(shù)的作用是指定數(shù)據(jù)庫游標(biāo)可以在記錄集中前后
移動(dòng) 并且當(dāng)前數(shù)據(jù)庫用戶獲取的記錄集對(duì)其他用戶的操作不敏感 就是說 當(dāng)前用戶正
在瀏覽記錄集中的數(shù)據(jù) 與此同時(shí) 其他用戶更新了數(shù)據(jù)庫中的數(shù)據(jù) 但是當(dāng)前用戶所獲
取的記錄集中的數(shù)據(jù)不會(huì)受到任何影響?
TYPE_SCROLL_SENSITIVE 該常數(shù)的作用是指定數(shù)據(jù)庫游標(biāo)可以在記錄集中前后移動(dòng) 并且當(dāng)前數(shù)據(jù)庫用戶獲取的記錄集對(duì)其他用戶的操作敏感 就是說 當(dāng)前用戶正在瀏覽記錄集 但是其它用戶的操作使數(shù)據(jù)庫中的數(shù)據(jù)發(fā)生了變化 當(dāng)前用戶所獲取的記錄集中的數(shù)據(jù)也會(huì)同步發(fā)生變化 這樣有可能會(huì)導(dǎo)致非常嚴(yán)重的錯(cuò)誤產(chǎn)生 建議慎重使用該常數(shù)?
CONCUR_READ_ONLY 該常數(shù)的作用是指定當(dāng)前記錄集的協(xié)作方式(concurrency mode)為只讀 一旦使用了這個(gè)常數(shù) 那么用戶就不可以更新記錄集中的數(shù)據(jù)? CONCUR_UPDATABLE 該常數(shù)的作用是指定當(dāng)前記錄集的協(xié)作方式(concurrency mode)為可以更新 一旦使用了這個(gè)常數(shù) 那么用戶就可以使用 updateXXX()等方法更新記錄集中的數(shù)據(jù)?
2 ResultSet接口提供了一整套的定位方法
這些可以在記錄集中定位到任意一行 具體有?
public boolean absolute(int? row);? 該方法的作用是將記錄集中的某一行設(shè)定為當(dāng)前行 亦即將數(shù)據(jù)庫游標(biāo)移動(dòng)到指定的行 參數(shù) row指定了目標(biāo)行的行號(hào) 這是絕對(duì)的行號(hào)由記錄集的第一行開始計(jì)算 不是相對(duì)的行號(hào)?
public boolean relative(int? rows);? 該方法的作用也是將記錄集中的某一行設(shè)定為當(dāng)前行 但是它的參數(shù) rows表示目標(biāo)行相對(duì)于當(dāng)前行的行號(hào) 例如當(dāng)前行是第3行 現(xiàn)在需要移動(dòng)到第5行去 既可以使用absolute()方法 也可以使用 relative()方法 代碼如下?
例?
rs.absolute(5);
或者
rs.relative(2);
其中rs代表ResultSet接口的實(shí)例對(duì)象?
又如當(dāng)前行是第5行 需要移動(dòng)到第 3行去 代碼如下?
例?
rs.absolute(3);
或者
rs.relative(-2);
其中rs代表ResultSet接口的實(shí)例對(duì)象?
讀者需要注意的問題是 傳遞給 relative()方法的參數(shù) 如果是正數(shù) 那么數(shù)據(jù)庫游標(biāo)向前移動(dòng) 如果是負(fù)數(shù) 那么數(shù)據(jù)庫游標(biāo)向后移動(dòng)?
注意 在本章中所說的數(shù)據(jù)庫游標(biāo)向前移動(dòng)是指向行號(hào)增大的方向移動(dòng) 向后移動(dòng)是指向行號(hào)減少的方向移動(dòng)?
public boolean first();? 該方法的作用是將當(dāng)前行定位到數(shù)據(jù)庫記錄集的第一行?
public boolean last();? 該方法的作用剛好和 first()方法相反 是將當(dāng)前行定位到數(shù)據(jù)庫記錄集的最后一行?
public boolean isFirst();? 該方法的作用是檢查當(dāng)前行是否記錄集的第一行 如果是返回true 否則 返回false?
public boolean isLast();?? 該方法的作用是檢查當(dāng)前行是否記錄集的最后一行 如果是 返回true 否則 返回false?
public void afterLast();? 該方法的作用是將數(shù)據(jù)庫游標(biāo)移到記錄集的最后 位于記錄集最后一行的后面 如果該記錄集不包含任何的行 該方法不產(chǎn)生作用?
public void beforeFirst();?? 該方法的作用是將數(shù)據(jù)庫游標(biāo)移到記錄集的最前面 位于記錄集第一行的前面 如果記錄集不包含任何的行 該方法不產(chǎn)生作用?
public boolean isAfterLast();? 該方法檢查數(shù)據(jù)庫游標(biāo)是否處于記錄集的最后面 如果是 返回true 否則 返回false?
public boolean isBeforeFirst();? 該方法檢查數(shù)據(jù)庫游標(biāo)是否處于記錄集的最前面 如果是 返回true 否則 返回false?
public boolean next();? 該方法的作用是將數(shù)據(jù)庫游標(biāo)向前移動(dòng)一位 使得下一行成為當(dāng)前行 當(dāng)剛剛打開記錄集對(duì)象時(shí) 數(shù)據(jù)庫游標(biāo)的位置在記錄集的最前面 第一次使用 next()方法 將會(huì)使數(shù)據(jù)庫游標(biāo)定位到記錄集的第一行 第二次使用 next()方法 將會(huì)使數(shù)據(jù)庫游標(biāo)定位到記錄集的第二行 以此類推?
注意 如果在當(dāng)前行打開了一個(gè)輸入流(Input Stream) 那么再次使用 next()方法時(shí)將會(huì)自動(dòng)關(guān)閉該輸入流?
public boolean previous();? 該方法的作用是將數(shù)據(jù)庫游標(biāo)向后移動(dòng)一位 使得上一行成為當(dāng)前行?
3 ResultSet接口添加了對(duì)行操作的支持
使用JDBC API 2.0 不僅可以任意將數(shù)據(jù)庫游標(biāo)定位到記錄集中的特定行 而且還可以使用ResultSet接口新定義的一套方法更新當(dāng)前行的數(shù)據(jù) 在以前 如果Java程序員希望更新記錄集中某行的數(shù)據(jù) 必須發(fā)送 SQL 語句給數(shù)據(jù)庫 程序員需要在 Java 代碼中嵌入冗長(zhǎng)的SQL語句 用以執(zhí)行 UPDATE DELETE INSERT 等數(shù)據(jù)庫操作 但是 當(dāng)JDBC API 2.0 出現(xiàn)時(shí) 一切就都改變了 程序員已經(jīng)可以部分拋開 SQL語言 享受Java編程的樂趣了 ResultSet接口中新添加的部分方法如下所示?
public boolean rowDeleted();? 如果當(dāng)前記錄集的某行被刪除了 那么記錄集中將會(huì)留
出一個(gè)空位 調(diào)用rowDeleted()方法 如果探測(cè)到空位的存在 那么就返回 true 如果沒有探測(cè)到空位的存在 就返回false值?
public boolean rowInserted();?? 如果當(dāng)前記錄集中插入了一個(gè)新行 該方法將返回true 否則返回false?
public boolean rowUpdated();?? 如果當(dāng)前記錄集的當(dāng)前行的數(shù)據(jù)被更新 該方法返回true 否則返回false?
public void insertRow();?? 該方法將執(zhí)行插入一個(gè)新行到當(dāng)前記錄集的操作?
public void updateRow();?? 該方法將更新當(dāng)前記錄集當(dāng)前行的數(shù)據(jù)?
public void deleteRow();? 該方法將刪除當(dāng)前記錄集的當(dāng)前行?
public void updateString(int columnIndex String x);? 該方法更新當(dāng)前記錄集當(dāng)前行某列的值 該列的數(shù)據(jù)類型是 String(指 Java 數(shù)據(jù)類型是 String 與之對(duì)應(yīng)的 JDBC 數(shù)據(jù)類型是VARCHAR或NVARCHAR 等數(shù)據(jù)類型) 該方法的參數(shù) columnIndex指定所要更新的列的列索引 第一列的列索引是 1 以此類推 第二個(gè)參數(shù) x 代表新的值 這個(gè)方法并不執(zhí)行數(shù)據(jù)庫操作 需要執(zhí)行 insertRow()方法或者 updateRow()方法以后 記錄集和數(shù)據(jù)庫中的數(shù)據(jù)才能夠真正更新?
public void updateString(String??? columnName String??? x);? 該方法和上面介紹的同名方法差不多 不過該方法的第一個(gè)參數(shù)是 columnName 代表需要更新的列的列名 而不是columnIndex?
ResultSet 接口中還定義了很多個(gè) updateXXX()方法 都和上面的兩個(gè)方法相類似 由于篇幅的原因 在這里就不詳細(xì)描述了 對(duì)此感興趣的讀者 可以參考相關(guān)的文獻(xiàn)?
往數(shù)據(jù)庫當(dāng)前記錄集插入新行的操作流程如下?
1 調(diào)用moveToInsertRow()方法?
2 調(diào)用updateXXX()方法 指定插入行各列的值?
3 調(diào)用insertRow()方法 往數(shù)據(jù)庫中插入新的行?
更新數(shù)據(jù)庫中某個(gè)記錄的值(某行的值)的方法是?
1 定位到需要修改的行(使用 absolute() relative()等方法定位)?
2 使用相應(yīng)updateXXX()方法設(shè)定某行某列的新值 XXX 所代表的Java 數(shù)據(jù)類型
必須可以映射為某列的JDBC數(shù)據(jù)類型 如果希望rollback該項(xiàng)操作 請(qǐng)?jiān)僬{(diào)用updateRow()方法以前使用cancelRowUpdates()方法 這個(gè)方法可以將某行某列的值復(fù)原?
3 使用updateRow()方法 完成 UPDATE 的操作?
刪除記錄集中某行(亦即刪除某個(gè)記錄)的方法?
1 定位到需要修改的行(使用 absolute() relative()等方法定位)?
2 使用deleteRow()方法?
4 新的ResultSet接口添加了對(duì) SQL3數(shù)據(jù)類型的支持
5 獲取記錄集行數(shù)的方法
1 首先使用last()方法 將數(shù)據(jù)庫游標(biāo)定位到記錄集的最后一行?
2 使用 getRow()方法 返回記錄集最后一行的行索引 該索引就等于記錄集所包
含記錄的個(gè)數(shù) 也就是記錄集的行數(shù)
9.2.2? 新的SQL語句接口(Statement 接口)
在JDBC API 2.0 中 SQL語句接口(Statement接口)也有了很大的改進(jìn) 功能更加強(qiáng)大? PreparedStatement接口和CallableStatement接口都繼承了 Statement接口 因此本小節(jié)也介紹這兩個(gè)接口相對(duì)于 JDBC API 1.0的改進(jìn)之處 因?yàn)樯鲜龅娜齻€(gè)接口都由Connection接口的方法創(chuàng)建 所以本小節(jié)也順便提一提 Connection接口?
1 Statement接口 CallableStatement接口 PreparesStatement接口的創(chuàng)建
這三個(gè)接口分別由Connection接口的createStatement() prepareStatement() prepareCall()等方法創(chuàng)建 這幾個(gè)方法的定義如下?
public Statement createStatement();
public Statement createStatement(int resultSetType int resultSetConcurrency);
public CallableStatement prepareCall(String sql);
public CallableStatement prepareCall(String sql int resultSetType?
int resultSetConcurrency);
public PreparedStatement prepareStatement(String sql);
public PreparedStatement prepareStatement(String sql int resultSetType?
?int resultSetConcurrency);
上面列出的方法中
參數(shù)sql代表需要執(zhí)行的 SQL語句? 這些 SQL語句不是完整的
SQL 語句 一般帶有 IN/OUT/INOUT 參數(shù) 參數(shù) resultSetType 代表該方法創(chuàng)建的 SQL 語句接口執(zhí)行 SQL 語句所返回的 ResultSet 的類型 例如 是否允許數(shù)據(jù)庫游標(biāo)前后移動(dòng)是否對(duì)其他用戶的數(shù)據(jù)庫更新操作敏感等 它們都是一些整型的常數(shù) 在ResultSet接口中定義了
參數(shù) resultSetConcurrency 代表該方法創(chuàng)建的SQL語句接口執(zhí)行SQL語句所返回的ResultSet的協(xié)同模式 如允許更新記錄集的數(shù)據(jù) 或者僅僅只讀 不能更新等 它們也是一些整型的常數(shù) 在ResultSet接口中定義了
例?
stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE?
ResultSet.CONCUR_UPDATABLE);
上面的代碼創(chuàng)建了一個(gè) SQL語句接口(Statement)的實(shí)例對(duì)象 該實(shí)例對(duì)象允許它執(zhí)行
SQL語句所返回的記錄集中的數(shù)據(jù)庫游標(biāo)前后移動(dòng) 允許更新記錄集中的數(shù)據(jù)?
2 支持批操作
Statement接口 PreparedStatement接口 CallableStatement接口都支持?jǐn)?shù)據(jù)庫批操作就是將若干個(gè) SQL 語句添加到一個(gè) SQL 語句塊(Batch)中 一并發(fā)送到數(shù)據(jù)庫服務(wù)器去數(shù)據(jù)庫引擎執(zhí)行完 SQL語句塊中的語句后 會(huì)將所有的結(jié)果一并返回 這種功能特別適用于大批量的數(shù)據(jù)庫 INSERT 操作 為了實(shí)現(xiàn)這樣的功能 必須用到的 Statement接口的方法
如下所示?
public void addBatch(String? sql);? 該方法用于將SQL語句添加到 SQL語句塊中?
public void clearBatch();?? 該方法用于將SQL語句塊中的所有SQL語句全部刪除?
public int[] executeBatch();? 該方法用于將 SQL語句塊發(fā)送到數(shù)據(jù)庫服務(wù)器去 并執(zhí)
行它 返回的結(jié)果是一個(gè)整型數(shù)組 數(shù)組中的元素是數(shù)據(jù)庫服務(wù)器執(zhí)行 SQL語句塊中SQL語句所返回的更新計(jì)數(shù) SQL語句塊中含有多少個(gè) SQL語句 返回的整行數(shù)組中就含有多少個(gè)元素?
使用JDBC API執(zhí)行數(shù)據(jù)庫批操作的方法是?
1 創(chuàng)建Statement接口的實(shí)例對(duì)象?
2 調(diào)用addBatch()方法 往SQL語句塊中添加若干個(gè)SQL語句?
3 使用executeBatch()方法 完成數(shù)據(jù)庫批操作
上面介紹的執(zhí)行數(shù)據(jù)庫批操作的方法僅僅適用于 Statement 接口 不適用于
PreparedStatement接口 CallableStatement接口 后面兩個(gè)接口定義了新的 addBatch()方法
該方法不需要任何參數(shù) 但是在Statement接口中定義的 addBatch()方法卻需要參數(shù) 參數(shù)是一個(gè)SQL語句 數(shù)據(jù)類型是String?
在 PreparedStatement接口 CallableStatement接口中實(shí)現(xiàn)數(shù)據(jù)庫批操作的方法是?
1 創(chuàng)建PreparedStatement接口或者CallableStatement接口的實(shí)例對(duì)象?
2 使用PreparedStatement 接口中定義的 setXXX()方法設(shè)定 SQL語句(該 SQL語句是在創(chuàng)建 PreparedStatement 接口或者 CallableStatement 接口的實(shí)例對(duì)象時(shí)初始化的)的IN/OUT/INOUT 參數(shù)的值(CallableStatement 接口并沒有定義任何 setXXX()方法 它的setXXX()方法全部繼承自PreparedStatement接口)??
3 使用executeBatch()方法該方法在Statement接口中定義不過PreparedStatement
接口和CallableStatement接口都繼承了這個(gè)方法?