關於面試到的一題:可滾動和可更新的結果集ResultSet

需求背景

 

1.對於一個只須要分析數據的程序來講,普通的ResultSet已夠用數據庫

2.但若是ResultSet用於顯示一張表或查詢結果的可視化數據顯示,數據結構

  1)會但願用戶在結果集上先後移動的需求,spa

  2)並且一旦展現告終果集的內容,用戶會但願修改這些內容,這有兩種方式:code

    (1)通常經過UPDATE語句修改(更高效)繼承

    (2)經過SELECT獲得ResultSet,再遍歷修改(意味着能夠細化修改操做!)接口

3.需求總結:細化修改操做,讓用戶能任意修改數據的交互程序,須要可滾動可更新的結果集ci

4.注意:不是全部的數據庫驅動程序都支持可滾動可更新的結果集資源

 

 

可滾動的結果集

 

1.默認的結果集不可滾動get

2.經過在Statement建立時填入ResultSet的相關參數(type,concurrency)開啓功能it

1

Statement stmt = conn.createStatement(type, concurrency);

1

PreparedStatement preStmt = conn.prepareStatement(command , type , concurrency);

 

3.ResultSet類的type值

TYPE_FORWARD_ONLY      結果集不能滾動(默認值)

TYPE_SCROLL_INSENSITIVE   結果集能夠滾動,但對數據庫變化不敏感

TYPE_SCROLL_SENSITIVE    結果集能夠滾動,對數據庫變化敏感

 

4.ResultSet類的concurrency值

CONCUR_READ_ONLY      結果集不能用於更新數據庫(默認值)

CONCUR_UPDATABLE      結果集能夠用於更新數據庫

 

 

5.示例

 

1)只想滾動遍歷結果集,而不想編輯數據

1

2

3

4

Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

 

//如今調用執行獲得的結果集就是可滾動的

ResultSet rs = stmt.executeQuery(query);

  可滾動的結果集有一個遊標,用以指示當前位置

 

2)結果集的滾動API

(1)將遊標向後移動:rs.previous()  (越界返回boolean值)

(2)相對位置:將遊標向前或向後移動n行:rs.relative(n)  (n爲正數向前移動,n爲負數向後移動,n爲0不移動,越界返回boolean值)

(3)絕對位置:將遊標移動到指定行:rs.absolute(n)

(4)返回行號:int currentRow = rs.getRow()  (第一行行號是1,越界返回boolean值) 

(5)其餘位置:first、last、beforeFirst、afterLast

(6)判斷:isFirst、isLast、isBeforeFirst、isAfterLast

 

 

 

可更新的結果集

 

1.得到可更新的結果集

1

Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);

 

2.並非設置參數以後全部的查詢都會返回可更新的結果集!

(1)若是查詢涉及多個表的鏈接,那麼它所產生的結果集是不可更新的;

(2)若是查詢只涉及一個表,或者是使用主鍵鏈接多個表的,那麼它將產生可更新的結果集;

(3)可調用ResultSet的getConcurrency方法來肯定能否更新

 

 

3.API(CRUD操做)

 

1)更新操做

(1)全部對應於SQL類型的數據類型都有updateXXX方法,與getXXX方法相似用法:必須指定列名稱序號

  ()一樣,這裏序號指的是該列在ResultSet中的序號

(2)updateXXX改變的只是結果集中對應行的值,而非數據庫中的值,當更新完行中的字段後,必需要調用updateRow方法提交到數據庫中,不然全部更新操做將被丟棄

 

2)新建操做

(1)插入行:使用moveToInsertRow將遊標移動到特定的位置

(2)建立行:調用updateXXX在插入行的位置上建立一個新的行

(3)回原行:調用moveToCurrentRow將遊標移回到調用moveToInsetRow方法以前的位置

1

2

3

4

5

6

7

8

9

10

11

12

13

//插入行的遊標位置是特定的,無需指定

rs.moveToInsertRow();

 

//在插入行插入數據

rs.updateString("Title", title);

rs.updateString("ISBN", isbn);

rs.updateString("Publisher_Id", pubid);

 

//提交建立

rs.insertRow();

 

//遊標回到原來的行

rs.moveToCurrentRow();

  注意:你沒法控制在結果集或數據庫中添加新數據的位置;對於在插入行中沒有指定值的列,將被設爲NULL值,但若是有NOT NULL約束,將拋出異常且這一行是沒法插入的

 

3)刪除操做

1

2

//刪除當前遊標所指的行

rs.deleteRow();

  deleteRow會當即將該行從結果集和數據庫中刪除

 

4)總結

  ResultSet接口中的updateRow、insertRow和deleteRow方法 的執行效果等同於SQL命令中的UPDATE、INSERT和DELETE

 

 

 

4.應用場景示例:

(1)想提升某些圖書的價格,但在執行UPDATE語句時又沒有一個簡單而同一個提價標準,這時須要遍從來修改,因此就用到了可滾動可更新的結果集,這時就比UPDATE靈活

1

2

3

4

5

6

7

8

9

10

11

12

13

14

String query = "SELECT * FROM Books";

ResultSet rs = stmt.executeQUERY(query);

 

while(rs.next()){

    //迭代結果集時,咱們就能夠根據業務條件來細化修改

    if(...){

        double increase = 。。。

        double price = rs.getDouble("Price");

        //更改結果集中當前行的字段值

        rs.updateDouble("Price",  price + increase);

        //將更改提交到數據庫,很關鍵不能漏

        rs.updateRow();

    }

}

 

 

優缺點

 

優勢細化修改操做,讓用戶能任意修改數據的交互程序

 

缺點:1.在與用戶的整個交互過程當中,必須始終與數據庫保持鏈接;

  後果:當用戶長時間離開時,數據庫鏈接長時間被佔用,而這屬於稀缺資源;

  解決:使用行集RowSet,RowSet繼承了ResultSet接口,卻無需始終保持與數據庫的鏈接~

     2.結果集不便於移動,由於數據結構複雜,且依賴於鏈接

  解決:使用行集RowSet,RowSet適用於將查詢結果移動到複雜應用的其餘層,或者其餘設備當中

相關文章
相關標籤/搜索