問題描述
ResultSet 表示 select 陳述句的查詢結果集,ResultSet 物件具有指向其當前資料行的指標, 最初,指標被置于第一行記錄之前,通過 next() 方法可以將指標移動到下一行記錄,
next() 方法在 ResultSet 物件沒有一行記錄時回傳 false ,因此可以在 while 回圈中使用它來遍歷結果集,也可以利用該方法判斷結果集是否為空,
示例代碼如下:
//此處省略連接資料庫的代碼...
Statement stmt =conn.createStatement();
ResultSet rs =stmr.executeQuery("select * from Test");
if(rs.next()){
System.out.println("結果集不為空!");
}
else{
System.out.println("結果集為空!");
}
此時出現第一個坑:Java 的 ResultSet 物件,默認是不可更新的,僅有一個向前移動的指標,
因此,只能遍歷它一次,并且只能按從第一行到最后一行的順序進行,
當你使用了 rs.next() 進行判斷后,會出現第一行資料丟失的情況,
這也是我一開始遇到的問題,
深究問題
ResultSet 的 Type 屬性
遇到問題后我第一想法是在搜索引擎上搜索相關解決辦法,但看了一圈具體有以下“解法”:
呼叫 rs.last() 方法,以獲取 ResultSet中 記錄的總數,然后呼叫 rs.beforeFirst() 方法將游標移回到第一條記錄前面
這種方法看上去可行,但當我實際修改后運行,卻出現報錯
Operation not allowed for a result set of type ResultSet.TYPE_FORWARD_ONLY.
這又是什么原因呢?
出現這個報錯的主要原因是:
ResultSet.TYPE_FORWARD_ONLY 型別的 ResultSet 只允許向前遍歷,不支持訪問先前的記錄或確定其大小,因此,使用 last() 和 getRow() 等方法都是不可行,
而 ResultSet 的 Type 屬性有如下幾種:
| 引數型別 | 說明 |
|---|---|
| ResultSet.TYPE_FORWORD_ONLY | 結果集的游標只能向下滾動 |
| ResultSet.TYPE_SCROLL_INSENSITIVE | 結果集的游標可以上下移動,當資料庫變化時,當前結果集不變 |
| ResultSet.TYPE_SCROLL_SENSITIVE | 回傳可滾動的結果集,當資料庫變化時,當前結果集同步改變 |
當 Statement stmt = conn.createStatement(); 中 的 createStatement() 預設時等價于: createStatement(ResultSet.TYPE_FORWORD_ONLY,ResultSet.CONCUR_READ_ONLY);
也就是結果集的游標只能向下滾動
所以才會出現 Operation not allowed for a result set of type ResultSet.TYPE_FORWARD_ONLY. 的報錯
也就是 ResultSet 默認情況下,只能使用 next() 方法向前逐行移動游標,而不支持 last()、first() 以及 absolute() 等方法,如果要使用 last()、absolute() 等方法,必須在由 Connection 生成 Statement 時指定相應的引數,格式如下:
Statement stmt =conn.ctrateStatement(游標型別,記錄更新權限);
解決辦法
-
手動指定游標型別
Statement stmt =conn.createStatement(ResultSet.TYPE_SCOLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); -
將 ResultSet 的內容復制到一個 List 中,然后檢查 List 是否為空
List<Object[]> results = new ArrayList<>(); while (rs.next()) { int columnCount = rs.getMetaData().getColumnCount(); Object[] row = new Object[columnCount]; for (int i = 1; i <= columnCount; i++) { row[i - 1] = rs.getObject(i); } results.add(row); } if (!results.isEmpty()) { // ResultSet不為空,可以執行讀取操作 } else { // ResultSet為空,不執行讀取操作 }請注意,在實際生產環境中,請考慮資料量和記憶體使用情況,因為將所有記錄復制到List中可能對記憶體產生很大影響,
-
定義 一個計數變數 i ,每次 next() 則 ++i ,在 while() 回圈結束后判斷 i 是否小于等于 0
int i = 0; while (resultSet.next()){ System.out.println(...); ++i; } if(i<=0) System.out.println(...);
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543384.html
標籤:Java
上一篇:day05-SpringMVC底層機制簡單實作-01
下一篇:Python裝飾器實體講解(一)
