Java JDBC學習實戰(二): 管理結果集

在我的上一篇博客《Java JDBC學習實戰(一): JDBC的基本操作》中,簡要介紹了jdbc開發的基本流程,并詳細介紹了Statement和PreparedStatement的使用:利用這兩個API可以執行SQL語句,完成基本的CURD操作。那么,當我們進行查詢操作,查詢到了結果集,該如何處理呢? Java提供了一個API,專門用于表示查詢的結果集——ResultSet。此外,還提供了一個結果集的分析工具——ResultSetMetaData。


一、 ResultSet的介紹

1.1 可移動、可更新的ResultSet
?《Java JDBC學習實戰(一): JDBC的基本操作》一文里,介紹過ResultSet的相關方法,可以通過一系列的方法來移動記錄指針,如:absolute、previous、next、first、last、beforeFirst、afterLast等方法。
ResultSet默認是不支持更新的,如果希望ResultSet完成更新操作,必須在創建Statement或PrepareStatement時傳入一些參數。
Connection對象在創建Statement或PrepareStatement時可以傳入兩個參數:
A、 resultSetType:控制ResultSet的類型,該參數有以下三個值:
? ? a、 ResultSet.TYPE_FORWARD_ONLY該常量控制記錄指針只能向前移動。
? ? b、 ResultSet.TYPE_SCROLL_INSENSITIVE:該常量控制記錄指針自由移動(可滾動結果集),但底層的數據改變不影響結果集ResultSet的內容
? ? c、 ResultSet.TYPE_SCROLL_SENSITIVE:該常量控制記錄指針自由移動,但底層數據的影響會改變結果集ResultSet的內容
B、 resultSetConcurrency:控制ResultSet的并發類型,該參數可以接收如下兩個值:
? ? a、 ResultSet.CONCUR_READ_ONLY:該常量表示ResultSet是只讀并發模式
? ? b、 ResultSet.CONCUR_UPDATABLE:該常量表示ResultSet是更新并發模式
通過PrepareStatement、Statement的創建時進行參數設置來創建可滾動、可更新的ResultSet,然后通過rs的updateXxx方法來完成某列的更新值設置,通過updateRow來提交修改。

// 使用Connection創建一個PreparedStatement對象
// 傳入控制結果集可滾動、可更新的參數
PreparedStatement pstmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);



1.2、 ResultSet中的二進制Blob數據處理

Blob類型通常用來存儲文件,如:圖片、音頻、視頻文件。將文件轉換成二進制保存在數據庫中,取出來的時候可以二進制數據恢復成文件。

如果要插入圖片到數據庫,顯然不能直接設置SQL參數拼接字符串進行插入。因為二進制常量無法表示。

但是將Blob類型數據插入到數據可以用PrepareStatement,通過PrepareStatement對象的setBinaryStream方法將參數傳入到二進制輸入流;也可以用Blob對象的getBytes方法直接取出數據。


二、 操作可滾動可更新的結果集

示例:(來自《瘋狂Java講義》)

public class ResultSetTest
{private String driver;private String url;private String user;private String pass;public void initParam(String paramFile)throws Exception{// 使用Properties類來加載屬性文件Properties props = new Properties();props.load(new FileInputStream(paramFile));driver = props.getProperty("driver");url = props.getProperty("url");user = props.getProperty("user");pass = props.getProperty("pass");}public void query(String sql)throws Exception{// 加載驅動Class.forName(driver);try(// 獲取數據庫連接Connection conn = DriverManager.getConnection(url, user , pass);// 使用Connection來創建一個PreparedStatement對象// 傳入控制結果集可滾動,可更新的參數。PreparedStatement pstmt = conn.prepareStatement(sql , ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);ResultSet rs = pstmt.executeQuery()){rs.last();// 指針移動到結果集的最后int rowCount = rs.getRow();for (int i = rowCount; i > 0 ; i-- ){rs.absolute(i);// 指針移動到指定位置System.out.println(rs.getString(1) + "\t"+ rs.getString(2) + "\t" + rs.getString(3));// 修改記錄指針所有記錄、第2列的值rs.updateString(2 , "學生名" + i);// 提交修改rs.updateRow();}}}public static void main(String[] args) throws Exception{ResultSetTest rt = new ResultSetTest();rt.initParam("mysql.ini");rt.query("select * from student_table");}
}


注: 如果要創建可更新的結果集,則使用查詢的數據通常只能來自一個數據表,而且查詢結果集中的數據列必須包含主鍵列,否則將會更新失敗。

三、 處理Blob類型數據

比如我們有如下數據表,表中的字段img_data類型為mediumblob,專門保存圖片數據

create table img_table(

? ?img_id int auto_increment primary key,

? ?img_name varchar(255),

? ?#創建一個mediumblob類型的數據列,用于保存圖片數據

? ?img_data mediumblob

);


之前已經講過,操作圖片數據,需要通過PrepareStatement對象的setBinaryStream方法來實現.

public void upload(String fileName)
{// 截取文件名String imageName = fileName.substring(fileName.lastIndexOf('\\')+ 1 , fileName.lastIndexOf('.'));File f = new File(fileName);try(InputStream is = new FileInputStream(f)){// 設置圖片名參數insert.setString(1, imageName);// 設置二進制流參數insert.setBinaryStream(2, is , (int)f.length());  int affect = insert.executeUpdate();if (affect == 1){// 重新更新ListModel,將會讓JList顯示最新的圖片列表fillListModel();}}catch (Exception e){e.printStackTrace();}
}	

可見,上述程序已經能完成圖片數據的插入操作,那如何讀取數據庫的圖片數據呢?ResultSet結果集可以直接通過getBlob()方法,得到Blob數據,可以再將其轉為Stream進行操作。

// ---------根據圖片ID來顯示圖片----------public void showImage(int id)throws SQLException{// 設置參數query.setInt(1, id);try(	// 執行查詢ResultSet rs = query.executeQuery()){if (rs.next()){// 取出Blob列Blob imgBlob = rs.getBlob(1);// 取出Blob列里的數據ImageIcon icon=new ImageIcon(imgBlob.getBytes(1L,(int)imgBlob.length()));imageLabel.setIcon(icon);}}}public static void main(String[] args)throws SQLException{new BlobTest().init();}
}


四、 使用ResultSetMetaData分析結果集

在我們查詢數據返回的結果集中,我們不清楚結果集存放的數據類型、數據列數。
那樣我們就可以用ResultSetMetaData來讀取ResultSet的信息。
通過ResultSet的getMetaData()的方法可以獲取ResultSetMetaData對象。
然后可以用ResultSetMetaData對象的方法來操作ResultSet,常用方法如下:
int getColumnCount():返回ResultSet的列名數量
int getColumnType(int column):返回指定索引的類型
String getColumnName(int column):返回指定索引的列名


     try(// 根據用戶輸入的SQL執行查詢ResultSet rs = stmt.executeQuery(sqlField.getText())){// 取出ResultSet的MetaDataResultSetMetaData rsmd = rs.getMetaData();Vector<String> columnNames = ?new Vector<>();Vector<Vector<String>> data = new Vector<>();// 把ResultSet的所有列名添加到Vector里for (int i = 0 ; i < rsmd.getColumnCount(); i++ ){columnNames.add(rsmd.getColumnName(i + 1));}// 把ResultSet的所有記錄添加到Vector里while (rs.next()){Vector<String> v = new Vector<>();for (int i = 0 ; i < rsmd.getColumnCount(); i++ ){v.add(rs.getString(i + 1));}data.add(v);}}catch (Exception e){e.printStackTrace();}


注:雖然,ResultSetMetaData可以準確地分析出ResultSet里包含了多少列,以及每列的列名、數據類型等,但使用ResuleSetMetaData需要一定的系統開銷,開發中盡量不要使用該API。

轉載于:https://www.cnblogs.com/hehe520/p/6330016.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/375596.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/375596.shtml
英文地址,請注明出處:http://en.pswp.cn/news/375596.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

error: storage size of ‘threads’ isn’t known

出錯的代碼行&#xff1a; pthread_t threads[NUM_THREADS];原因&#xff1a; NUM_THREADS 無值 原先&#xff1a; #define NUM_THREADS修改為 #define NUM_THREADS 5

android之相機開發

http://blog.csdn.net/jason0539/article/details/10125017 android之相機開發 分類&#xff1a; android 基礎知識2013-08-20 22:32 9774人閱讀 評論(2) 收藏 舉報Android在android中應用相機功能&#xff0c;一般有兩種&#xff1a;一種是直接調用系統相機&#xff0c;一種自…

文件和文件夾權限-Win7公共盤中出現大量臨時文件

公司中有一個文件服務器&#xff0c;給不同部門和員工設置了不同的權限&#xff0c;最近有員工&#xff08;沒有修改權限&#xff0c;有讀取及執行,讀取,寫入&#xff09;反映在公共盤上修改文件的時候會產生大量的臨時文件&#xff0c;添加上修改權限之后就可以了&#xff0c;…

Duilib編輯框Edit輸入完自動跳到下一個編輯框

首先xml文件中設置edit的maxchar參數&#xff0c;默認255好像。 <edit maxchar"10" />然后在notify函數中加入以下代碼 if (msg.sType _T("textchanged")) {if (static_cast<CEditUI*>(msg.pSender)->GetMaxChar() msg.pSender->GetT…

Mysql數據庫安全管理配置

1.刪除test庫 原因&#xff1a; The default MySQL installation comes with a database named test that anyone can access. This database is intended only for tutorials, samples, testing, etc. Databases named "test" and also databases with names starti…

duilib清空richedit內容

推薦使用以下方法&#xff1a; m_pRichEdit->SetSelAll(); m_pRichEdit->Clear();不推薦使用以下方法&#xff1a; m_pRichEdit->SetText("");雖然效果是一樣的&#xff0c;但是當編輯框中文本存在多種格式的時候&#xff0c;第二種方法會存在問題&#x…

新學了一個用python編寫的簡單的百度貼吧帖子的爬蟲

# -*- coding: utf-8 -*- #--------------------------------------- # 作者&#xff1a;chendn # 語言&#xff1a;Python 2.7.10 #---------------------------------------import string,urllib2 def tieba(url,beginPage,endPage):for i in range(beginPage,endPage1):…

duilib自定義消息

/** NOTE: All Message Numbers below 0x0400 are RESERVED.** Private Window Messages Start Here:*/ #define WM_USER 0x0400從WM_USER往上加就行了

BZOJ 2190儀仗隊【歐拉函數】

問題的唯一難點就是如何表示隊長能看到的人數&#xff1f;如果建系&#xff0c;隊長所在的點為&#xff08;0,0&#xff09;分析幾組數據就一目了然了&#xff0c;如果隊長能看到的點為(m,n),那么gcd&#xff08;m&#xff0c;n&#xff09;1即m n 互質或者是&#xff08;0,1&a…

Codeforces Round #318 (Div. 2) B Bear and Three Musketeers (暴力)

算一下復雜度。發現可以直接暴。對于u枚舉a和b&#xff0c;判斷一下是否連邊&#xff0c;更新答案。 #include<bits/stdc.h> using namespace std;int n,m; const int maxn 4001; #define PB push_back vector<int> G[maxn]; bool g[maxn][maxn]; int deg[maxn]; …

form表單,submit,ajax提交

尼瑪... 一個簡單的表單提交&#xff0c;竟然給我整的直郁悶。 本來就是個保存功能&#xff0c;幾個前人都用的ajax提交&#xff0c;我也就沒改成submit。然后坑爹的就來了。 我在表單里寫了個<form></form>&#xff08;實際用ajax提交&#xff0c;也沒必要寫這個標…

windows 文件對話框

https://docs.microsoft.com/zh-cn/previous-versions/windows/desktop/legacy/bb776913(vvs.85)

python開發技術詳解(一)

python是一門簡單靈動的語言。從今天開始我要每天都做筆記&#xff0c;每天都要寫博客記錄我所想&#xff0c;我所學到的。 筆記提綱&#xff1a; 1&#xff0c;python的簡單介紹&#xff0c;python的編譯用法&#xff0c;有什么要注意的。 2&#xff0c;命名規則 3&#xff0c…

(Android Studio)添加文本框

此文大部分摘自http://hukai.me/android-training-course-in-chinese/basics/firstapp/building-ui.html android : id 這是定義View的唯一標識符。可以在程序代碼中通過該標識符對對象進行引用&#xff0c;例如對這個對象進行讀和修改的操作(在下一課里將會用到)。 當想從XML里…

java final keyword

依據上下文環境&#xff0c;java的keywordfinal也存在著細微的差別&#xff0c;但通常指的是“這是無法改變的。”不想改變的理由由兩種&#xff1a;一種是效率&#xff0c;還有一種是設計。因為兩個原因相差非常遠&#xff0c;所以關鍵子final可能被吳用。 接下來介紹一下使用…

聽GPT 講Rust源代碼--src/tools(24)

File: rust/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs 在Rust源代碼中的rust/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs文件是Clippy項目的一個規則&#xff0c;用于檢查可能是誤用或錯誤的Box引用情況。 Rust中的Box是一個堆分配的值的所有權…

遞歸乘法

遞歸乘法。 寫一個遞歸函數&#xff0c;不使用 * 運算符&#xff0c; 實現兩個正整數的相乘。可以使用加號、減號、位移&#xff0c;但要吝嗇一些。 示例1: 輸入&#xff1a;A 1, B 10輸出&#xff1a;10示例2: 輸入&#xff1a;A 3, B 4輸出&#xff1a;12提示: 保證乘法…

Building a RESTful Web Service

http://spring.io/guides/gs/rest-service/ Should shutdown tomcat service first , and then java -jar *.jar轉載于:https://www.cnblogs.com/churuosi/p/4774151.html

IOS的各種手勢

轉自http://blog.csdn.net/likendsl/article/details/7554150 一、概述 iPhone中處理觸摸屏的操作&#xff0c;在3.2之前是主要使用的是由UIResponder而來的如下4種方式&#xff1a; - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesCancell…