//*************************************************************************** // (c) Copyright IBM Corp. 2007 All rights reserved. // // The following sample of source code ("Sample") is owned by International // Business Machines Corporation or one of its subsidiaries ("IBM") and is // copyrighted and licensed, not sold. You may use, copy, modify, and // distribute the Sample in any form without payment to IBM, for the purpose of // assisting you in the development of your applications. // // The Sample code is provided to you on an "AS IS" basis, without warranty of // any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR // IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Some jurisdictions do // not allow for the exclusion or limitation of implied warranties, so the above // limitations or exclusions may not apply to you. IBM shall not be liable for // any damages you suffer as a result of using, copying, modifying or // distributing the Sample, even if IBM has been advised of the possibility of // such damages. //*************************************************************************** // // SOURCE FILE NAME: DbRsHold.java // // SAMPLE: How to use result set cursor holdability in DB2 JDBC Type 2 Driver // for Linux, UNIX and Windows and Universal JDBC driver. The // Universal JDBC driver implements the result set cursor holdability // APIS specified in JDBC3. To compile this sample, you need JDK1.4 // or above; To run this sample, you need JRE1.4 or above. // // SQL Statements Used: // SELECT // UPDATE // // Classes used from Util.java are: // Db // Data // JdbcException // // // Output will vary depending on the JDBC driver connectivity used. //*************************************************************************** // // For more information on the sample programs, see the README file. // // For information on developing Java applications see the Developing Java Applications book. // // For information on using SQL statements, see the SQL Reference. // // For the latest information on programming, compiling, and running DB2 // applications, visit the DB2 Information Center at // http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp //**************************************************************************/ import java.io.*; import java.lang.*; import java.util.*; import java.sql.*; import javax.sql.*; public class DbRsHold { // The SQL statements used in this sample static final String sqlQuery = "SELECT empno, firstnme, lastname, salary " + " FROM employee WHERE workdept='A00'"; static final String sqlUpdt = "SELECT empno, firstnme, lastname, salary\n" + " FROM employee WHERE workdept='A00'" + " FOR UPDATE of salary"; static double salaryInc = 0.0; public static void main(String[] args) { if( args.length > 5 || ( args.length == 1 && ( args[0].equals( "?" ) || args[0].equals( "-?" ) || args[0].equals( "/?" ) || args[0].equalsIgnoreCase( "-h" ) || args[0].equalsIgnoreCase( "/h" ) || args[0].equalsIgnoreCase( "-help" ) || args[0].equalsIgnoreCase( "/help" ) ) ) ) { System.out.println( "Usage: prog_name [dbAlias] [userId passwd] " + "(use DB2 JDBC type 2 Driver)\n" + " prog_name -u2 [dbAlias] [userId passwd] " + "(use universal JDBC type 2 driver)\n" + " prog_name [dbAlias] server portNum userId passwd " + "(use universal JDBC type 4 driver)"); System.exit(0); } if(args.length == 0 || (args.length > 0 && args.length <= 3 && !args[0].equalsIgnoreCase("-u2"))) { holdabilityOfLegacyType2(args); } else { // Check the JRE version. JRE1.4 or above is required String jreVersion = System.getProperty("java.version"); StringTokenizer token = new StringTokenizer(jreVersion, "."); String simpVersion = jreVersion; if(token.hasMoreTokens()) simpVersion = token.nextToken(); if(token.hasMoreTokens()) simpVersion = simpVersion + "." + token.nextToken(); float fVersion = (new Float(simpVersion)).floatValue(); if(fVersion < (float)1.4) { System.out.println("To run this sample by using the Universal JDBC" + " driver, you need JRE1.4 or above"); System.exit(0); } holdabilityOfUniversalDriver(args); } } //main static void holdabilityOfLegacyType2(String[] args) { // Db class is used to connect to the database // Variable connDd is the connection that displays data in the table Db dbDd = null; Connection connDd = null; try { dbDd = new Db(args); connDd = dbDd.connect(); } catch (Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } // Set cursor holdability at connection level: CURSORHOLD = 1 System.out.println( "-----------------------------------------------------------------\n" + "Set cursor holdability at connection level: CURSORHOLD = 1\n"); salaryInc = 2000.0; setHoldabilityLegacyType2(args, 1, connDd); // Set cursor holdability at connection level: CURSORHOLD = 0 // SQLException is expected since the cursor will be closed at commit System.out.println( "-----------------------------------------------------------------\n" + "Set cursor holdability at connection level: CURSORHOLD = 0\n" + " 'CLI0125E Function sequence error' " + "IS EXPECTED AFTER THE FIRST COMMIT\n"); setHoldabilityLegacyType2(args, 0, connDd); // Recover data in the table System.out.println( "-----------------------------------------------------------------\n"); System.out.println("......Data Recovery......"); salaryInc = -2000.0; setHoldabilityLegacyType2(args, 1, connDd); System.out.println("'CLI0125E Function sequence error' " + "IS EXPECTED AFTER THE FIRST COMMIT\n"); setHoldabilityLegacyType2(args, 0, connDd); System.out.println("......Data Recovery Complete......"); System.out.println( "-----------------------------------------------------------------"); try { dbDd.disconnect(); } catch (Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } } //holdabilityOfLegacyType2 // This method shows how to set cursor holdability by legacy type 2 driver static void setHoldabilityLegacyType2(String[] args, int holdability, Connection connDd) { ResultSet rs = null; Connection conn = null; String dbUrl = null; try { // Set the connection properties Properties connProp = new Properties(); if(args.length == 2) { connProp.setProperty("UID", args[0]); connProp.setProperty("PWD", args[1]); } else if (args.length == 3) { connProp.setProperty("UID", args[1]); connProp.setProperty("PWD", args[2]); } connProp.setProperty("CURSORHOLD", (new Integer(holdability)).toString()); if (args.length == 1 || args.length == 3) dbUrl = "jdbc:db2:" + args[0]; else dbUrl = "jdbc:db2:sample"; // Get a connection conn = DriverManager.getConnection(dbUrl, connProp); conn.setAutoCommit(false); // Create a statement with the holdability of the connection Statement stmt = conn.createStatement(); // Execute the query and obtain the result set rs = stmt.executeQuery(sqlUpdt); String curName = rs.getCursorName(); // Create a statement for updating data Statement stmt1 = conn.createStatement(); System.out.println("Original data:"); displayData(connDd); int num = 1; while (rs.next()) { System.out.println("UPDATE salary: row " + num); float salary = rs.getFloat("SALARY"); stmt1.executeUpdate("UPDATE employee" + " SET salary = " + (float)(salary + salaryInc) + " WHERE CURRENT OF " + curName); // If CURSORHOLD is 1, the cursor is still open after commit; // If CURSORHOLD is 0, the cursor is closed after commit. conn.commit(); System.out.println("COMMIT updates: row " + num); displayData(connDd); num ++; } } catch (Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } finally { try { if (rs != null) rs.close(); if (conn != null) conn.close(); } catch(Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } } } //setHoldabilityLegacyType2 static void holdabilityOfUniversalDriver(String[] args) { // Db class is used to connect to the database // Variable conn is the connection that shows cursor holdability changes // Variable connDd is the connection that displays data in the table Db db = null; Db dbDd = null; Connection conn = null; Connection connDd = null; try { db = new Db(args); conn = db.connect(); dbDd = new Db(args); connDd = dbDd.connect(); } catch (Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } // Print different types of result set cursor holdability System.out.println( "-----------------------------------------------------------------\n" + "ResultSet.HOLD_CURSORS_OVER_COMMIT = " + ResultSet.HOLD_CURSORS_OVER_COMMIT); System.out.println( "ResultSet.CLOSE_CURSORS_AT_COMMIT = " + ResultSet.CLOSE_CURSORS_AT_COMMIT + "\n"); // Set cursor holdability at connection level: HOLD_CURSORS_OVER_COMMIT System.out.println( "-----------------------------------------------------------------\n" + "Set cursor holdability at connection level: " + "HOLD_CURSORS_OVER_COMMIT\n"); salaryInc = 2000.00; setHoldabilityAtConnection(conn, ResultSet.HOLD_CURSORS_OVER_COMMIT, connDd); // Set cursor holdability at connection level: CLOSE_CURSORS_AT_COMMIT // SQLException is expected since the cursor will be closed at commit System.out.println( "-----------------------------------------------------------------\n" + "Set cursor holdability at connection level: " + "CLOSE_CURSORS_AT_COMMIT\n" + "'Result set closed' ERROR IS EXPECTED AFTER THE FIRST COMMIT\n"); setHoldabilityAtConnection(conn, ResultSet.CLOSE_CURSORS_AT_COMMIT, connDd); // Set cursor holdability at statement level: HOLD_CURSORS_OVER_COMMIT System.out.println( "-----------------------------------------------------------------\n" + "Set cursor holdability at statement level: " + "HOLD_CURSORS_OVER_COMMIT"); salaryInc = -2000.0; setHoldabilityAtStatement(conn, ResultSet.HOLD_CURSORS_OVER_COMMIT, connDd); // Set cursor holdability at statement level: CLOSE_CURSORS_AT_COMMIT // SQLException is expected since the cursor will be closed at commit System.out.println( "-----------------------------------------------------------------\n" + "Set cursor holdability at statement level: " + "CLOSE_CURSORS_AT_COMMIT\n" + "'Result set closed' ERROR IS EXPECTED AFTER THE FIRST COMMIT\n"); setHoldabilityAtStatement(conn, ResultSet.CLOSE_CURSORS_AT_COMMIT, connDd); System.out.println( "-----------------------------------------------------------------"); try { db.disconnect(); dbDd.disconnect(); } catch (Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } } // holdabilityOfUniversalDriver // This method shows how to set cursor holdability at the connection level static void setHoldabilityAtConnection(Connection conn, int holdability, Connection connDd) { ResultSet rs = null; try { // Set cursor holdability at the connection level conn.setHoldability(holdability); // Print the cursor holdability of the connection System.out.println("Connection.getHoldability = " + conn.getHoldability()); // Print the database MetaData supports for cursor holdability DatabaseMetaData dbMeta = conn.getMetaData(); System.out.println("DatabaseMetaData.getResultSetHoldability = " + dbMeta.getResultSetHoldability()); System.out.println(" Supports HOLD_CURSORS_OVER_COMMIT = " + dbMeta.supportsResultSetHoldability( ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println(" Supports CLOSE_CURSORS_AT_COMMIT = " + dbMeta.supportsResultSetHoldability( ResultSet.CLOSE_CURSORS_AT_COMMIT)); // Create a statement with the holdability from the connection Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); // Print the cursor holdability of the statement, // which should be same as the connection's System.out.println("Statement.getResultSetHoldability = " + stmt.getResultSetHoldability() + "\n"); // Execute the query and obtain the result set rs = stmt.executeQuery(sqlQuery); // Update rows in the result set and commit one by one updateData(conn, rs, connDd); } catch (Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } finally { try { if (rs != null) rs.close(); } catch(Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } } } // setHoldabilityAtConnection // This method shows how to set cursor holdability at the statement level static void setHoldabilityAtStatement(Connection conn, int holdability, Connection connDd) { ResultSet rs = null; try { // Print the cursor holdability of the connection System.out.println("Connection.getHoldability = " + conn.getHoldability()); // Print the database MetaData supports for cursor holdability DatabaseMetaData dbMeta = conn.getMetaData(); System.out.println("DatabaseMetaData.getResultSetHoldability = " + dbMeta.getResultSetHoldability()); System.out.println(" Supports HOLD_CURSORS_OVER_COMMIT = " + dbMeta.supportsResultSetHoldability( ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println(" Supports CLOSE_CURSORS_AT_COMMIT = " + dbMeta.supportsResultSetHoldability( ResultSet.CLOSE_CURSORS_AT_COMMIT)); // Set cursor holdability at the statement level // which can override the connection's PreparedStatement prepStmt = conn.prepareStatement(sqlQuery, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, holdability); // Print the cursor holdability of the statement, // which can be different from the connection's System.out.println("Statement.getResultSetHoldability = " + (prepStmt).getResultSetHoldability() + "\n"); // Execute the query and obtain the result set rs = prepStmt.executeQuery(); // Update rows in the result set and commit one by one updateData(conn, rs, connDd); } catch (Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } finally { try { if (rs != null) rs.close(); } catch (Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } } } // setHoldabilityAtStatement // This method updates the rows in the result set and commit one by one. // Depending on the result set cursor holdability, the cursor is open or // closed each commits. static void updateData(Connection conn, ResultSet rs, Connection connDd) { try { System.out.println("Original data:"); displayData(connDd); int num = 1; while (rs.next()) { System.out.println("UPDATE salary: row " + num); float salary = rs.getFloat("SALARY"); rs.updateFloat("SALARY", (float)(salary + salaryInc)); rs.updateRow(); // If cursor holdability is HOLD_CURSORS_OVER_COMMIT, // the cursor is still open after commit; // If cursor holdability is CLOSE_CURSORS_AT_COMMIT, // the cursor is closed after commit. System.out.println("COMMIT updates: row " + num); conn.commit(); displayData(connDd); num ++; } } catch (Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } } // updateData // This method is a helping method. It displays the content // in the EMPLOYEE table and reflects the data updates. static void displayData(Connection connDd) { ResultSet rs = null; try { // Create a prepared statement to execute the query PreparedStatement prepStmt = connDd.prepareStatement(sqlQuery, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); // Execute the query and obtain the result set rs = prepStmt.executeQuery(); // Print the content of the result set System.out.println( " EMPNO NAME SALARY\n" + " ------ ------------------- ----------"); while (rs.next()) System.out.println(" " + Data.format(rs.getString("EMPNO"), 7) + Data.format(rs.getString("FIRSTNME") + " " + rs.getString("LASTNAME"), 20) + rs.getFloat("SALARY")); System.out.println(); connDd.commit(); } catch (Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } finally { try { if (rs != null) rs.close(); } catch (Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } } } // displayData } // DbRsHold