「Java ResultSetチュートリアル」

JavaのResultSetインターフェースは、java.sqlパッケージの一部です。これはJDBCフレームワークのコアコンポーネントの一つです。ResultSetオブジェクトは、リレーショナルデータベースから取得したクエリ結果にアクセスするために使用されます。

ResultSetは、クエリ結果の一行を指すカーソル/ポインタを保持しています。ResultSetが提供するナビゲーションやゲッターメソッドを使用することで、データベースのレコードに一つずつアクセスすることができます。また、ResultSetはデータの更新にも使用することができます。

JavaのResultSetの階層構造

Java ResultSet Class Hierarchy

上記の図は、JDBCフレームワークにおけるResultSetの位置を示しています。ResultSetは、Statement、PreparedStatement、またはCallableStatementを使用してSQLクエリを実行することで取得することができます。

AutoCloseable、Wrapper は ResultSet のスーパーインターフェースです。今回は、Java プログラムで ResultSet をどのように扱うかを見ていきましょう。

例えば、結果セットの例

以下のDBスクリプトを使用して、データベースとテーブルを作成し、いくつかのレコードを追加します。例としてMySQLを使用します。

create database empdb;

use empdb;

create table tblemployee (empid integer primary key, firstname varchar(32), lastname varchar(32), dob date);

insert into tblemployee values  (1, 'Mike', 'Davis',' 1998-11-11');
insert into tblemployee values  (2, 'Josh', 'Martin', '1988-10-22');
insert into tblemployee values  (3, 'Ricky', 'Smith', '1999-05-11');

以下の例プログラムを見て、テーブルからレコードを取得してコンソールに表示しましょう。プロジェクトのクラスパスにMySQL JDBCドライバがあることを確認してください。

package com.scdev.examples;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Date;

/**
 * Java Resultset Example of Retrieving records.
 * 
 * @author scdev
 *
 */

public class ResultSetDemo {

	public static void main(String[] args) {
		String query = "select empid, firstname, lastname, dob from tblemployee";
		Connection conn = null;
		Statement stmt = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/empdb", "root", "root");
			stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(query);
			while (rs.next()) {
				Integer empId = rs.getInt(1);
				String firstName = rs.getString(2);
				String lastName = rs.getString(3);
				Date dob = rs.getDate(4);
				System.out.println("empId:" + empId);
				System.out.println("firstName:" + firstName);
				System.out.println("lastName:" + lastName);
				System.out.println("dob:" + dob);
				System.out.println("");
			}
			rs.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				stmt.close();
				conn.close();
			} catch (Exception e) {}
		}
	}
}

出力:

empId:1
firstName:Mike
lastName:Davis
dob:1998-11-11

empId:2
firstName:Josh
lastName:Martin
dob:1988-10-22

empId:3
firstName:Ricky
lastName:Smith
dob:1999-05-11

説明:

  • ResultSet is obtained by calling the executeQuery method on Statement instance. Initially, the cursor of ResultSet points to the position before the first row.
  • The method next of ResultSet moves the cursor to the next row. It returns true if there is further row otherwise it returns false.
  • We can obtain data from ResultSet using getter methods provided by it. e.g.  getInt(),  getString(),  getDate()
  • All the getter methods have two variants. 1st variant takes column index as Parameter and 2nd variant accepts column name as Parameter.
  • Finally, we need to call close method on ResultSet instance so that all resources are cleaned up properly.

結果セットのタイプと同時処理

ステートメント、プリペアドステートメント、またはキャラブルステートメントのインスタンスを作成する際に、ResultSetのタイプと並行性を指定することができます。

statement.createStatementメソッドは、resultSetTypeとresultSetConcurrencyの引数を使って実行します。

結果セットの種類

1) 前方のみ(ResultSet.TYPE_FORWARD_ONLY)

このタイプのResultSetインスタンスは、最初の行から最後の行に向かってのみ移動できます。ResultSetは、next()メソッドを呼び出すことで一度に1行前に移動することができます。このタイプのResultSetは、Statement、PreparedStatement、またはCallableStatementのインスタンスを作成する際に取得できます。

Statement stmt = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery("select * from tbluser");

2) スクロール不可視 (ResultSet.TYPE_SCROLL_INSENSITIVE)

スクロール非感応の結果セットは、前方および後方の両方の方向にスクロールすることができます。また、absolute()メソッドを使用して絶対位置にスクロールすることもできます。しかし、データの変更には感応しません。クエリが実行され、結果セットが取得された時点でのデータのみを持っています。取得後に行われたデータの変更は反映されません。

Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,  		ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery("select * from tbluser");

3) スクロールセンシティブな(ResultSet.TYPE_SCROLL_SENSITIVE)

スクロールセンシティブなResultSetは、前方および後方の両方向にスクロールすることができます。また、absolute()メソッドを呼び出すことで、絶対位置にスクロールすることもできます。ただし、このResultSetはデータの変更に敏感です。オープンされている間に行われた変更を反映します。

Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,  		ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery("select * from tbluser");

結果セットの同時性

1)読み取り専用 (ResultSet.CONCUR_READ_ONLY)

これはデフォルトの同時実行モデルです。ResultSetインスタンスでの読み取り専用操作のみが許可されており、更新操作は許可されていません。

2) アップデート可能な(ResultSet.CONCUR_UPDATABLE)

この場合、私たちはResultSetインスタンス上で更新操作を実行することができます。

結果セットのメソッド

ResultSetのメソッドは、以下のカテゴリに分けることができます。

  • Navigational Methods
  • Getter/Reader Methods
  • Setter/Updater Methods
  • Miscellaneous Methods – close() and getMetaData()

1. ResultSetのナビゲーションメソッド

  • boolean absolute(int row) throws SQLException**:** This method moves ResultSet cursor to the specified row and returns true if the operation is successful.
  • void afterLast() throws SQLException**:** This method moves ResultSet cursor to the position after the last row.
  • void beforeFirst() throws SQLException**:** This method moves ResultSet cursor to the position before the first row.
  • boolean first() throws SQLException: This method moves ResultSet cursor to the first row.
  • boolean last() throws SQLException: This method moves ResultSet cursor to the last row.
  • boolean next() throws SQLException: This method moves ResultSet cursor to the next row.
  • boolean previous() throws SQLException: This method moves ResultSet cursor to the previous row.
package com.scdev.examples;
import java.sql.*;

/**
 * Java Resultset Example using navigational methods.
 * 
 * @author scdev
 *
 */
public class ResultSetDemo {

	public static void main(String[] args) {
		String query = "select empid, firstname, lastname, dob from tblemployee";
		Connection conn = null;
		Statement stmt = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/empdb", "root", "root");
			stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
			ResultSet rs = stmt.executeQuery(query);
			System.out.println("All the rows of table=>");
			while (rs.next()) { 
				// Go to next row by calling next() method
				displayData(rs);
			}
			System.out.println("Now go directly to 2nd row=>");
			rs.absolute(2); // Go directly to 2nd row
			displayData(rs);
			System.out.println("Now go to Previous row=>");
			rs.previous(); 
			// Go to 1st row which is previous of 2nd row
			displayData(rs);
			rs.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				stmt.close();
				conn.close();
			} catch (Exception e) {
			}
		}
	}

	public static void displayData(ResultSet rs) throws SQLException {
		System.out.println("empId:" + rs.getInt(1));
		System.out.println("firstName:" + rs.getString(2));
		System.out.println("lastName:" + rs.getString(3));
		System.out.println("dob:" + rs.getDate(4));
		System.out.println("");
	}
}

出力:

All the rows of table=>
empId:1
firstName:Mike
lastName:Davis
dob:1998-11-11

empId:2
firstName:Josh
lastName:Martin
dob:1988-10-22

empId:3
firstName:Ricky
lastName:Smith
dob:1999-05-11

Now go directly to 2nd row=>
empId:2
firstName:Josh
lastName:Martin
dob:1988-10-22

Now go to Previous row=>
empId:1
firstName:Mike
lastName:Davis
dob:1998-11-11

2. ResultSetの取得/読み取りメソッド

  • int getInt(int columnIndex) throws SQLException: This method returns value of specified columnIndex as int.
  • long getLong(int columnIndex) throws SQLException: This method returns value of specified columnIndex as long
  • String getString(int columnIndex) throws SQLException: This method returns value of specified columnIndex as String
  • java.sql.Date getDate(int columnIndex) throws SQLException: This method returns value of specified columnIndex as java.sql.Date
  • int getInt(String columnLabel) throws SQLException: This method returns value of specified column name as int.
  • long getLong(String columnLabel) throws SQLException: This method returns value of specified column name as long.
  • String getString(String columnLabel) throws SQLException: This method returns the value of the specified column name as String.
  • java.sql.Date getDate(String columnLabel) throws SQLException: This method returns the value of the specified column name as java.sql.Date.
  • ResultSet contains getter methods that return other primitive datatypes like boolean, float and double. It also has methods to obtain array and binary data from the database.

3. ResultSetのセッター/アップデーターメソッド

  • void updateInt(int columnIndex, int x) throws SQLException: This method updates the value of specified column of current row with int value.
  • void updateLong(int columnIndex, long x) throws SQLException: This method updates the value of the specified column of the current row with long value.
  • void updateString(int columnIndex, String x) throws SQLException: This method updates the value of the specified column of the current row with a String value.
  • void updateDate(int columnIndex, java.sql.Date x) throws SQLException: This method updates the value of specified column of current row with java.sql.Date value.
  • void updateInt(String columnLabel, int x) throws SQLException: This method updates the value of the specified column label of the current row with int value.
  • void updateLong(String columnLabel, long x) throws SQLException: This method updates the value of the specified column label of the current row with long value.
  • void updateString(String columnLabel, String x) throws SQLException: This method updates the value of the specified column label of the current row with a String value.
  • void updateDate(String columnLabel, java.sql.Date x) throws SQLException: This method updates the value of specified columnLabel of current row with java.sql.Date value.

注意:セッター/アップデータメソッドは直接データベースの値を更新しません。データベースの値は、insertRowメソッドまたはupdateRowメソッドを呼び出した後に挿入または更新されます。

package com.scdev.examples;
import java.sql.*;

/**
 * Java Resultset Example using updater methods.
 * 
 * @author scdev
 *
 */

public class ResultSetUpdateDemo {

	public static void main(String[] args) {
		String query = "select empid, firstname, lastname, dob from tblemployee";
		Connection conn = null;
		Statement stmt = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/empdb", "root", "root");
			stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
			ResultSet rs = stmt.executeQuery(query);
			System.out.println("Now go directly to 2nd row for Update");
			if (rs.absolute(2)) { 
				// Go directly to 2nd row
				System.out.println("Existing Name:" + rs.getString("firstName"));
				rs.updateString("firstname", "Tyson");
				rs.updateRow();
			}
			rs.beforeFirst(); // go to start
			System.out.println("All the rows of table=>");
			while (rs.next()) { 
			// Go to next row by calling next() method
				displayData(rs);
			}
			rs.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				stmt.close();
				conn.close();
			} catch (Exception e) {
			}
		}
	}

	public static void displayData(ResultSet rs) throws SQLException {
		System.out.println("empId:" + rs.getInt(1));
		System.out.println("firstName:" + rs.getString(2));
		System.out.println("lastName:" + rs.getString(3));
		System.out.println("dob:" + rs.getDate(4));
		System.out.println("");
	}
}

出力:

Now go directly to 2nd row for Update
Existing Name:Josh
All the rows of table=>
empId:1
firstName:Mike
lastName:Davis
dob:1998-11-11

empId:2
firstName:Tyson
lastName:Martin
dob:1988-10-22

empId:3
firstName:Ricky
lastName:Smith
dob:1999-05-11

4. 結果セットのその他のメソッド

  • void close() throws SQLException**:** This method frees up resources associated with ResultSet Instance. It must be called otherwise it will result in resource leakage.
  • ResultSetMetaData getMetaData() throws SQLException: This method returns ResultSetMetaData instance. It gives information about the type and property of columns of the query output.

参考: Java ドキュメント

コメントを残す 0

Your email address will not be published. Required fields are marked *