クエリを介してレコードのリストをフェッチする場合、必要に応じて更新を行ったり来たりできるオブジェクトにレコードを保存する必要があることがよくあります。この記事では、明示的なコードとサンプルシナリオを使用して、データベースプログラミングで一般的に必要とされるこの手法について説明します。
ResultSetについて
ResultSet java.sqlで定義されたインターフェースです。 パッケージ。 ステートメントによって返されるデータのテーブルを表します 物体。 ステートメント オブジェクトは、データベースへのSQLクエリを実行するために使用されます。 ResultSetオブジェクトは、データベーステーブルの現在のレコードを指すカーソルを維持します。その結果、 first()を使用して、さまざまな行に前後に配置するために効果的に使用できます。 、 previous() 、 next() 、および last() 要件に応じた方法。最初に、 ResultSet オブジェクトは、最初の行の前の場所に配置されます。これがResultSetの理由です トラバーサルは常に次のように始まります:
while(resultSet.next()) { // ... }
ResultSetに注意してください next()を実行すると、オブジェクトが最初の行に配置されます。 すでに述べたように、 ResultSet は、ループに入るときのメソッドです。 オブジェクトは、最初は最初の行の直前の位置にあります。したがって、たとえば、有効なレコードを取得するには、少なくとも最初の行に配置する必要があります。ポインタ/インデックスが指している配列位置の値-1と見なされる場合があります。配列から任意の種類の有効な値を取得するには、最初に少なくとも0の場所に再配置する必要があります。
これで、前述したように、 ResultSetを使用してレコードをスクロールできます。 物体。ただし、この機能はデフォルトでは提供されません。 ResultSetのデフォルトの動作 オブジェクトは更新可能ではなく、所有するカーソルは実際には一方向に移動し、前方にのみ移動します。これは、レコードを1回だけ、そして順方向にのみ反復できることを意味します。ただし、 ResultSet になるように、柔軟にする方法があります。 更新可能であるだけでなく、スクロール可能です。
2つの別々のプログラムですぐにわかります。
スクロール可能なResultSet
まず、 ResultSetを作成しましょう オブジェクトはスクロール可能です。 スクロール可能 これは、 ResultSet オブジェクトが作成されたので、フェッチしたレコードを順方向と逆方向の任意の方向にトラバースできます。これにより、最後のレコード、最初のレコード、次のレコード、および前のレコードを読み取ることができます。
package org.mano.example; import java.sql.*; public class App { static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost:3306/employees"; static final String USER = "root"; static final String PASS = "secret"; static final String SQL = "SELECT * FROM employees ORDER BY first_name"; public static void main( String[] args ) { Connection connection = null; ResultSet rs = null; try { Class.forName(JDBC_DRIVER); connection = DriverManager.getConnection (DB_URL, USER, PASS); System.out.println("n1. Connection established"); }catch(Exception ex) { ex.printStackTrace(); } try (PreparedStatement pstmt = connection.prepareStatement(SQL, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);){ System.out.println("n2. Executing SQL query..."); rs = pstmt.executeQuery(); System.out.println("n3. ResultSet object created successfully."); System.out.println("n4. Now some RecordSet scrolling starts..."); rs.first(); show(rs); rs.last(); show(rs); rs.previous(); rs.previous(); show(rs); rs.next(); show(rs); System.out.println("nn5. That's all. RecordSet scrolling ends."); }catch(SQLException ex){ ex.printStackTrace(); }finally{ try { connection.close(); }catch(SQLException ex){ } } } public static void show(ResultSet rs) throws SQLException{ System.out.printf ("n--------------------------------"+ "-------------------------------------"); System.out.printf("n%7d | %10s | %10s | %s | %s | %s ",rs.getLong("emp_no"), rs.getString("first_name"), rs.getString("last_name"), rs.getDate("birth_date").toString(), rs.getDate("hire_date"), rs.getString("gender")); System.out.printf ("n---------------------------------"+ "------------------------------------"); } }
出力
- 接続が確立されました。
- SQLクエリを実行しています…
- ResultSetオブジェクトが正常に作成されました。
- これで、いくつかのRecordSetスクロールが開始されます…
------------------------------------------------------------- 497615 | Aamer | McDermid | 1954-11-18 | 1985-04-24 | M ------------------------------------------------------------- ------------------------------------------------------------- 484995 | Zvonko | Lakshmanan | 1964-11-04 | 1992-12-04 | M ------------------------------------------------------------- ------------------------------------------------------------- 482000 | Zvonko | Cannata | 1960-11-23 | 1986-08-13 | M ------------------------------------------------------------- ------------------------------------------------------------- 483497 | Zvonko | Pollacia | 1961-12-26 | 1985-08-01 | M -------------------------------------------------------------
- それだけです。 RecordSetのスクロールが終了します。
スクロール可能なResultSet オブジェクトは、 executeQuery()の実行結果です。 ステートメントのインスタンスを介して取得されたメソッド またはPreparedStatement 。 ResultSetのタイプ 作成するオブジェクトは、ステートメントに対して明示的に宣言する必要があります 定義されたスクロールタイプ定数を介してオブジェクト。
- ResultSet.TYPE_FORWARD_ONLY: これがデフォルトのタイプです。
- ResultSet.TYPE_SCROLL_INSENSITIVE: 前後の移動を有効にしますが、 ResultSetの影響を受けません。 更新。
- ResultSet.TYPE_SCROLL_SENSITIVE: 前後の移動を有効にしますが、 ResultSetの影響を受けます 更新。
CONCUR_READ_ONLY など、他にも使用される定数があります 、つまり、 ResultSet 更新可能ではありません。別の定数CONCUR_UPDATABLEがあります 、これは反対を意味し、 ResultSet を意味します 更新可能です。
更新可能なResultSet
更新可能なResultSetの作成 これは、それが指すレコードがトラバース可能であるだけでなく、更新可能であることを意味します。変更はすぐにデータベースに保持され、 ResultSetに反映されます。 リアルタイムでオブジェクト。
package org.mano.example; import java.sql.*; public class App { static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost:3306/employees"; static final String USER = "root"; static final String PASS = "secret"; static final String SQL = "SELECT * FROM employees WHERE emp_no = ?"; public static void main( String[] args ) { Connection connection = null; ResultSet rs = null; long emp_no = 484995; try { Class.forName(JDBC_DRIVER); connection = DriverManager.getConnection (DB_URL, USER, PASS); System.out.println("n1. Connection established"); }catch(Exception ex) { ex.printStackTrace(); } try(PreparedStatement pstmt = connection.prepareStatement(SQL, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);){ pstmt.setLong(1,emp_no); System.out.println("n2. Executing SQL query..."); rs = pstmt.executeQuery(); System.out.println("n3. ResultSet object created successfully."); while(rs.next()){ show(rs); String fname = rs.getString("first_name"); System.out.println("n4. Updating name "+fname+" to Subham"); rs.updateString("first_name", "Subham"); rs.updateRow(); } System.out.println("nn5. Record updated. See below."); rs.previous(); show(rs); }catch(SQLException ex){ ex.printStackTrace(); }finally{ try { rs.close(); connection.close(); }catch(SQLException ex){ } } } public static void show(ResultSet rs) throwsSQLException{ System.out.printf ("n--------------------------------"+ "-------------------------------------"); System.out.printf("n%7d | %10s | %10s | %s | %s | %s ",rs.getLong("emp_no"), rs.getString("first_name"), rs.getString("last_name"), rs.getDate("birth_date").toString(), rs.getDate("hire_date"), rs.getString("gender")); System.out.printf ("n---------------------------------"+ "------------------------------------"); } }
更新可能なResultSet フェッチされたレコードを前後にトラバースして比較を行った後、特定の値を更新する場合に特に便利です。作成プロセスは前のプログラムと似ていますが、 ResultSet ここで使用される定数はTYPE_SCROLL_SENSITIVE およびCONCUR_UPDATABLE 。
結論
ResultSet のデフォルトの動作とは異なり、 これにより、オブジェクトの柔軟性が向上します。この機能をアプリケーションで活用して、レコードをトラバースするだけでなく、レコードを更新可能にして、より良いサービスを提供できるようにすることもできます。結果セットの標準的な動作は、スクロール可能な ResultSet と比較すると、非常に非効率的です。 、独自の用途があるため、かけがえのないものです。