Server-side Java: Use JDBC for industrial-strength performance, Part 2

Follow these Java server-side data -mining patterns with multiple ResultSets for maximum performance

1 2 3 4 Page 2
Page 2 of 4

The code at a glance

The database table structure used by the JDBC calling code is simply a table named test that contains two columns (id:integer and fname:varchar). In addition to the table, a stored procedure is required. The stored procedure simply performs two select statements in the test table. The implementation of the stored procedure in a TransactSQL-oriented database (such as Sybase or MS SQL Server) is:

CREATE PROCEDURE reverseSelectionProcedure AS BEGIN -- First select statement, producing a 1-column JDBC ResultSet select fName from testlogin.Test;

-- Second select statement, producing a 2-column JDBC ResultSet select * from testlogin.Test; END

The structure of all code samples in this article follow the same pattern: they inherit all functionality, except the main() method, from the MultipleResultsets class. The main() method is fully implemented in each subclass. This complete exclusion code is given in favor of the more elegant abstract factory pattern (see the Resources section below for more information) to improve readability.

Figure 2. Scenario for using multiple ResultSets

The following is the method call sequence:

  1. main() calls setupConnection(), which creates the Logger and returns a fully set-up JDBC connection to the database.
  2. A PreparedStatement is created from appropriate SQL. Note that CallableStatement extends PreparedStatement.
  3. processStatement() is called to print out some status data from the given PreparedStatement.
  4. main() closes the Statement from step 2 and Connection from step 1.

The only helper class used is the Logger, which logs messages to a file or the standard output stream, depending on its construction. The only relevant method call of the Logger class is the log() method. Below is the code structure for all scenarios.

First, here is the code structure of the Logger class:


/** * Class that logs messages to a file or the * standard output stream. */ public class Logger { /** Stream connected to the output file. */ private PrintWriter out;

/** * Constructor to invoke if all messages of * this Logger should be directed to the file * with the supplied filename. * <br>NOTE! The contents of the given file is * erased before any message is written to it. * * @param logFileName Name of the logfile. */ public Logger(String logFileName) { try { // Create the log stream out = new PrintWriter(new FileWriter(logFileName), true); } catch(IOException ex) { System.out.println(" [Logger Constructor]: " + "Could not create the logFile (" + logFileName + ")."); System.out.println(" [Logger Constructor]: " + "Reason is " + ex); } }

/** * Constructor to invoke if all messages of this Logger should * be redirected to the standard output stream. */ public Logger() { }

/** * Prints the given message to the log stream, and * appends a newline character. * * @param msg Message to log. */ public void log(String msg) { // Log the message if(out == null) System.out.println(msg); else out.println(msg); } }

The common superclass of the examples used in this article is MultipleResultsets, as seen below. It provides two services: setting up the database connection (including loading the drivers) and processing the results of the entire PreparedStatement, which holds the SQL query to the database.

1 2 3 4 Page 2
Page 2 of 4