前面介紹了經過JDBC如何管理數據庫,當時提到Statement專門提供了executeQuery方法用於查詢操做,爲何查詢操做這麼特殊呢?這是由於其它語句跑完一次就了事了,頂多像insert、update、delete再返回受影響的記錄數量,但select命令跟它們不同,查詢語句可能會返回多條記錄,每條記錄又包含多個字段。似此多條記錄多個字段的情景,返回值不管定義爲哪一種類型都不太好辦,故而乾脆給個單獨的executeQuery方法,該方法的返回值也設置成專屬的ResultSet類型,表示查詢方法返回了一個結果集,詳細的記錄結果請到結果集中遍歷得到。
據此可將記錄查詢的操做過程分紅如下四個步驟:
一、獲取數據庫鏈接:該步驟調用DriverManager類的getConnection方法得到鏈接對象。
二、建立該鏈接的執行報告:該步驟調用Connection對象的createStatement方法得到執行報告。
三、命令報告執行查詢語句:該步驟調用報告對象的executeQuery方法來執行查詢語句,並返回查詢記錄的結果集。
四、循環遍歷結果集裏面的全部記錄:一般該步驟需調用結果集對象的next方法不斷日後遍歷,也就是將結果集的指示遊標一步一步向後移動。在遍歷過程中,可能要調用結果集對象的其它方法進一步操做,ResultSet的常見方法分紅三類,說明以下:
一、移動遊標
該類方法可將當前遊標移動到指定位置,主要包括下列方法:
next:將遊標移到後一條記錄。該方法返回true表示還沒有移到末尾,返回false表示已經移到末尾。
absolute:將遊標移到第幾條記錄,若是參數爲負數則表示倒數的第幾條。
first:將遊標移到第一條記錄。
last:將遊標移到最後一條記錄。
previous:將遊標移到前一條記錄。
beforeFirst:將遊標移到第一條記錄以前。
afterLast:將遊標移到最後一條記錄以後。
二、判斷遊標位置
該類方法可判斷當前遊標是否處於某個位置,主要包括下列方法:
isFirst:遊標是否指向第一條記錄。
isLast:遊標是否指向最後一條記錄。
isBeforeFirst:遊標是否在第一條記錄以前。
isAfterLast:遊標是否在最後一條記錄以後。
三、從當前遊標獲取數據
該類方法可從當前遊標指向的記錄中獲取字段值,當方法參數爲整型時,表示獲取指定序號的字段值;當方法參數爲字符串時,表示獲取指定名稱的字段值。相關的獲取方法羅列以下:
getInt:獲取指定序號或者指定名稱的字段整型值。
getLong:獲取指定序號或者指定名稱的字段長整值。
getFloat:獲取指定序號或者指定名稱的字段浮點值。
getDouble:獲取指定序號或者指定名稱的字段雙精度值。
getString:獲取指定序號或者指定名稱的字段字符串值。
getDate:獲取指定序號或者指定名稱的字段日期值。html
接下來舉幾個具體應用的例子,首先要從teacher表中查詢全部記錄,則依次鏈接數據庫、建立鏈接的報告、執行查詢語句,再循環遍歷結果集獲取每條記錄的字段信息。這一連串的查詢代碼示例以下:sql
// 查詢全部記錄(默認排序) private static void showAllRecord() { String sql = "select * from teacher"; // 鏈接數據庫、建立鏈接的報告、執行查詢語句 try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { while (rs.next()) { // 循環遍歷結果集裏面的全部記錄 int gonghao = rs.getInt("gonghao"); // 獲取指定字段的整型值 String name = rs.getString("name"); // 獲取指定字段的字符串值 Date birthday = rs.getDate("birthday"); // 獲取指定字段的日期值 int sex = rs.getInt("sex"); // 獲取指定字段的整型值 String course = rs.getString("course"); // 獲取指定字段的字符串值 String desc = String.format("工號爲%d,姓名爲%s,出生日期爲%s,性別爲%s,任教課程爲%s。", gonghao, name, getFormatDate(birthday), sex==0 ? "男性" : "女性", course); System.out.println("當前教師信息爲:"+desc); } } catch (SQLException e) { e.printStackTrace(); } }
注意MySQL未提供將日期轉成字符串的to_char函數,於是只能先取到Date類型的字段值,再將其經過Java代碼轉爲字符串。日期類型轉換爲字符串類型的方法代碼以下所示:數據庫
// 獲取指定格式的日期字符串 public static String getFormatDate(Date date) { // 建立一個日期格式化的工具 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 將當前日期時間按照指定格式輸出格式化後的日期時間字符串 return sdf.format(date); }
接着運行上面的查詢方法showAllRecord,觀察到日誌窗口完整輸出了以下的五條記錄信息。函數
當前教師信息爲:工號爲1,姓名爲張老師,出生日期爲1983-03-03,性別爲女性,任教課程爲語文。 當前教師信息爲:工號爲2,姓名爲李老師,出生日期爲1984-04-04,性別爲男性,任教課程爲數學。 當前教師信息爲:工號爲3,姓名爲王老師,出生日期爲1985-05-05,性別爲女性,任教課程爲英語。 當前教師信息爲:工號爲4,姓名爲趙老師,出生日期爲1986-06-06,性別爲男性,任教課程爲物理。 當前教師信息爲:工號爲5,姓名爲劉老師,出生日期爲1987-07-07,性別爲女性,任教課程爲化學。
而後在原語句增長排序條件,讓全部記錄按照生日字段降序排列,則修改後的查詢代碼以下所示:工具
// 查詢全部記錄(按照生日倒序) private static void showAllRecordByBirthday() { String sql = "select * from teacher order by birthday desc"; // 鏈接數據庫、建立鏈接的報告、執行查詢語句 try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { while (rs.next()) { // 循環遍歷結果集裏面的全部記錄 int gonghao = rs.getInt("gonghao"); // 獲取指定字段的整型值 String name = rs.getString("name"); // 獲取指定字段的字符串值 Date birthday = rs.getDate("birthday"); // 獲取指定字段的日期值 int sex = rs.getInt("sex"); // 獲取指定字段的整型值 String course = rs.getString("course"); // 獲取指定字段的字符串值 String desc = String.format("工號爲%d,姓名爲%s,出生日期爲%s,性別爲%s,任教課程爲%s。", gonghao, name, getFormatDate(birthday), sex==0 ? "男性" : "女性", course); System.out.println("當前教師信息爲:"+desc); } } catch (SQLException e) { e.printStackTrace(); } }
增長了showAllRecordByBirthday方法以後,再次運行測試程序,從日誌窗口可見此次的記錄結果以生日字段降序顯示了。測試
當前教師信息爲:工號爲5,姓名爲劉老師,出生日期爲1987-07-07,性別爲女性,任教課程爲化學。 當前教師信息爲:工號爲4,姓名爲趙老師,出生日期爲1986-06-06,性別爲男性,任教課程爲物理。 當前教師信息爲:工號爲3,姓名爲王老師,出生日期爲1985-05-05,性別爲女性,任教課程爲英語。 當前教師信息爲:工號爲2,姓名爲李老師,出生日期爲1984-04-04,性別爲男性,任教課程爲數學。 當前教師信息爲:工號爲1,姓名爲張老師,出生日期爲1983-03-03,性別爲女性,任教課程爲語文。
排序條件僅僅調整返回記錄的順序,然而分組條件就不同了。由於分組條件存在統計操做,像count、sum、max這些函數只返回運算結果,但從結果集中取數據有賴於字段名稱,因此須要在統計函數以後加個別名,至關於該函數的運算結果暫存於該別名變量。好比表達式「count(sex) count」說的就是計數結果以count命名,遊標從count字段獲取到的即爲計數值。下面是對teacher表按照性別字段分組統計的查詢代碼例子:日誌
// 查詢性別分組。注意要給count之類的函數結果分配別名 private static void showRecordGroupBySex() { String sql = "select sex,count(sex) count from teacher group by sex order by sex asc"; // 鏈接數據庫、建立鏈接的報告、執行查詢語句 try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { while (rs.next()) { // 循環遍歷結果集裏面的全部記錄 int sex = rs.getInt("sex"); // 獲取指定字段的整型值 int count = rs.getInt("count"); // 獲取指定字段的整型值 String desc = String.format("%s老師有%d位;", sex==0 ? "男" : "女", count); System.out.print(desc); } } catch (SQLException e) { e.printStackTrace(); } }
運行包含showRecordGroupBySex方法的測試程序,果真正確輸出了預期的統計日誌以下所示。orm
男老師有2位;女老師有3位;
更多Java技術文章參見《Java開發筆記(序)章節目錄》htm