FileDocCategorySizeDatePackage
PooledStatement.javaAPI DocExample25064Mon Mar 31 23:10:16 BST 2003org.dasein.persist

PooledStatement.java

/* $Id$ */
/* Copyright © 2002 George Reese, Imaginet */
package org.dasein.persist;

// Developed by George Reese for the book:
// Java Best Practices, Volume II: J2EE
// Ported to the digital@jwt code library by George Reese

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;

/**
 * A logical statement handed to applications as an abstraction
 * of the underlying pooled prepared statement.
 * <br/>
 * Last modified $Date$
 * @version $Revision$
 * @author George Reese
 */
public class PooledStatement implements PreparedStatement {
    /**
     * The logical connection responsible for this statement.
     */
    private Connection        connection = null;
    /**
     * The list of listeners interested in closings of this statement.
     */
    private ArrayList         listeners  = new ArrayList();
    /**
     * The SQL behind this prepared statement.
     */
    private String            sql        = null;
    /**
     * The underlying physical statement.
     */
    private PreparedStatement statement  = null;

    /**
     * Constructs a new pooled statement tied to the specified
     * logical connection and prepared statement.
     * @param conn the logical database connection
     * @param sql the SQL this statemment represents
     * @param stmt the physical prepared statement
     */
    public PooledStatement(Connection conn, String sql,
                           PreparedStatement stmt) {
        super();
        this.sql = sql;
        statement = stmt;
    }

    /**
     * Delegates to the underlying prepared statement.
     * @throws java.sql.SQLException a database error occurred
     */
    public void addBatch() throws SQLException {
        validate();
        statement.addBatch();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param sql unused
     * @throws java.sql.SQLException a database error occurred
     */
    public void addBatch(String sql) throws SQLException {
        validate();
        statement.addBatch(sql);
    }

    /**
     * Adds a listener to this statement's list of listeners.
     * @param lstnr the listener to add
     */
    public void addStatementEventListener(StatementEventListener lstnr) {
        synchronized( listeners ) {
            listeners.add(lstnr);
        }
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @throws java.sql.SQLException a database error occurred
     */
    public void cancel() throws SQLException {
        validate();
        statement.cancel();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @throws java.sql.SQLException a database error occurred
     */
    public void clearBatch() throws SQLException {
        validate();
        statement.clearBatch();
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @throws java.sql.SQLException a database error occurred
     */
    public void clearParameters() throws SQLException {
        validate();
        statement.clearParameters();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @throws java.sql.SQLException a database error occurred
     */
    public void clearWarnings() throws SQLException {
        validate();
        statement.clearWarnings();
    }

    /**
     * Closes this logical statementand notifies all listeners of
     * the closure so that the physical statement can return to the pool.
     * All parameters and warnings associated with the statement
     * are cleared.
     * @throws java.sql.SQLException a database error occurred
     */
    public void close() throws SQLException {
        validate();
        statement.clearParameters();
        statement.clearWarnings();
        statement = null;
        synchronized( listeners ) {
            Iterator it = listeners.iterator();

            while( it.hasNext() ) {
                StatementEventListener lstnr;

                lstnr = (StatementEventListener)it.next();
                lstnr.statementClosed(new StatementEvent(sql, statement));
            }
        }
    }

    /**
     * Delegates to the underlying prepared statement.
     * @return true if the execution generated results
     * @throws java.sql.SQLException a database error occurred
     */
    public boolean execute() throws SQLException {
        validate();
        return statement.execute();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param sql necessary from the <code>Statement</code> interface
     * @return true if the execution generated results
     * @throws java.sql.SQLException a database error occurred
     */
    public boolean execute(String sql) throws SQLException {
        validate();
        return statement.execute(sql);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @return an array of update counts
     * @throws java.sql.SQLException a database error occurred
     */
    public int[] executeBatch() throws SQLException {
        validate();
        return statement.executeBatch();
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @return the query results
     * @throws java.sql.SQLException a database error occurred
     */
    public ResultSet executeQuery() throws SQLException {
        validate();
        return statement.executeQuery();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param sql nonsense
     * @return the query results
     * @throws java.sql.SQLException a database error occurred
     */
    public ResultSet executeQuery(String sql) throws SQLException {
        validate();
        return statement.executeQuery(sql);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @return the number of updated rows
     * @throws java.sql.SQLException a database error occurred
     */
    public int executeUpdate() throws SQLException {
        validate();
        return statement.executeUpdate();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param sql nonsense
     * @return the number of updated rows
     * @throws java.sql.SQLException a database error occurred
     */
    public int executeUpdate(String sql) throws SQLException {
        validate();
        return statement.executeUpdate(sql);
    }

    /**
     * Provides the logical connection associated with this statement
     * @return the statement's connection
     * @throws java.sql.SQLException a database error occurred
     */
    public Connection getConnection() throws SQLException {
        validate();
        return connection;
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @return the fetch direction
     * @throws java.sql.SQLException a database error occurred
     */
    public int getFetchDirection() throws SQLException {
        validate();
        return statement.getFetchDirection();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @return the fetch size
     * @throws java.sql.SQLException a database error occurred
     */
    public int getFetchSize() throws SQLException {
        validate();
        return statement.getFetchSize();
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @return the maximum field size
     * @throws java.sql.SQLException a database error occurred
     */
    public int getMaxFieldSize() throws SQLException {
        validate();
        return statement.getMaxFieldSize();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @return the maximum number of rows
     * @throws java.sql.SQLException a database error occurred
     */
    public int getMaxRows() throws SQLException {
        validate();
        return statement.getMaxRows();
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @return the result set meta-data
     * @throws java.sql.SQLException a database error occurred
     */
    public ResultSetMetaData getMetaData() throws SQLException {
        validate();
        return statement.getMetaData();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @return more results!
     * @throws java.sql.SQLException a database error occurred
     */
    public boolean getMoreResults() throws SQLException {
        validate();
        return statement.getMoreResults();
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @return the query timeout
     * @throws java.sql.SQLException a database error occurred
     */
    public int getQueryTimeout() throws SQLException {
        validate();
        return statement.getQueryTimeout();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @return the lastt result set
     * @throws java.sql.SQLException a database error occurred
     */
    public ResultSet getResultSet() throws SQLException {
        validate();
        return statement.getResultSet();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @return the concurrency for result sets
     * @throws java.sql.SQLException a database error occurred
     */
    public int getResultSetConcurrency() throws SQLException {
        validate();
        return statement.getResultSetConcurrency();
    }

    /**
     * Delegates to the underlying prepared statement.
     * @return the type for result sets
     * @throws java.sql.SQLException a database error occurred
     */
    public int getResultSetType() throws SQLException {
        validate();
        return statement.getResultSetType();
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @return the number of rows updated
     * @throws java.sql.SQLException a database error occurred
     */
    public int getUpdateCount() throws SQLException {
        validate();
        return statement.getUpdateCount();
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @return any warnings
     * @throws java.sql.SQLException a database error occurred
     */
    public SQLWarning getWarnings() throws SQLException {
        validate();
        return statement.getWarnings();
    }

    /**
     * @return true if no statement exists
     */
    public boolean isClosed() throws SQLException {
        return (statement == null);
    }

    /**
     * Removes a listener from the stable of listeners.
     * @param lstnr the listener to remove
     */
    public void removeStatementEventListener(StatementEventListener lstnr) {
        synchronized( listeners ) {
            listeners.remove(lstnr);
        }
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param arr an array value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setArray(int idx, Array arr) throws SQLException {
        validate();
        statement.setArray(idx, arr);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param is the input stream
     * @param len the length of the stream
     * @throws java.sql.SQLException a database error occurred
     */
    public void setAsciiStream(int idx, InputStream is, int len)
        throws SQLException {
        validate();
        statement.setAsciiStream(idx, is, len);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param d the big decimal value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setBigDecimal(int idx, BigDecimal d) throws SQLException {
        validate();
        statement.setBigDecimal(idx, d);
    }
 
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param is the input stream
     * @param len the lenth of the input stream
     * @throws java.sql.SQLException a database error occurred
     */
    public void setBinaryStream(int idx, InputStream is, int len)
        throws SQLException {
        validate();
        statement.setBinaryStream(idx, is, len);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param bthe blob value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setBlob(int idx, Blob b) throws SQLException {
        validate();
        statement.setBlob(idx, b);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param b the boolean value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setBoolean(int idx, boolean b) throws SQLException {
        validate();
        statement.setBoolean(idx, b);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param b the byte value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setByte(int idx, byte b) throws SQLException {
        validate();
        statement.setByte(idx, b);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param data the binary data
     * @throws java.sql.SQLException a database error occurred
     */
    public void setBytes(int idx, byte[] data) throws SQLException {
        validate();
        statement.setBytes(idx, data);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param rdr the reader from which the value should be read
     * @param len the length of the stream
     * @throws java.sql.SQLException a database error occurred
     */
    public void setCharacterStream(int idx, Reader rdr, int len)
        throws SQLException {
        validate();
        statement.setCharacterStream(idx, rdr, len);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param c the character large object value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setClob(int idx, Clob c) throws SQLException {
        validate();
        statement.setClob(idx, c);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param name the name of the cursor
     * @throws java.sql.SQLException a database error occurred
     */
    public void setCursorName(String name) throws SQLException {
        validate();
        statement.setCursorName(name);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param d the date value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setDate(int idx, Date d) throws SQLException {
        validate();
        statement.setDate(idx, d);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param d the date value
     * @param cal the calendar of the date
     * @throws java.sql.SQLException a database error occurred
     */
    public void setDate(int idx, Date d, Calendar cal) throws SQLException {
        validate();
        statement.setDate(idx, d, cal);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param d the double value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setDouble(int idx, double d) throws SQLException {
        validate();
        statement.setDouble(idx, d);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param en whether to enable escape processing
     * @throws java.sql.SQLException a database error occurred
     */
    public void setEscapeProcessing(boolean en) throws SQLException {
        validate();
        statement.setEscapeProcessing(en);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx dir the fetch direction
     * @throws java.sql.SQLException a database error occurred
     */
    public void setFetchDirection(int dir) throws SQLException {
        validate();
        statement.setFetchDirection(dir);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param sz the fetch size
     * @throws java.sql.SQLException a database error occurred
     */
    public void setFetchSize(int sz) throws SQLException {
        validate();
        statement.setFetchSize(sz);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param f the float value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setFloat(int idx, float f) throws SQLException {
        validate();
        statement.setFloat(idx, f);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param x the integer value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setInt(int idx, int x) throws SQLException {
        validate();
        statement.setInt(idx, x);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param l the long value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setLong(int idx, long l) throws SQLException {
        validate();
        statement.setLong(idx, l);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param max the maximum field size
     * @throws java.sql.SQLException a database error occurred
     */
    public void setMaxFieldSize(int max) throws SQLException {
        validate();
        statement.setMaxFieldSize(max);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param max the maximum number of rows
     * @throws java.sql.SQLException a database error occurred
     */
    public void setMaxRows(int max) throws SQLException {
        validate();
        statement.setMaxRows(max);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param type the type from <code>java.sql.Types</code>
     * @throws java.sql.SQLException a database error occurred
     * @see java.sql.Types
     */
    public void setNull(int idx, int type) throws SQLException {
        validate();
        statement.setNull(idx, type);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param type the type from <code>java.sql.Types</code>
     * @param name the user defined type name
     * @throws java.sql.SQLException a database error occurred
     * @see java.sql.Types
     */
    public void setNull(int idx, int type, String name) throws SQLException {
        validate();
        statement.setNull(idx, type, name);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param ob the object value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setObject(int idx, Object ob) throws SQLException {
        validate();
        statement.setObject(idx, ob);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param ob the object value
     * @param type the type from <code>java.sql.Types</code>
     * @throws java.sql.SQLException a database error occurred
     * @see java.sql.Types
     */
    public void setObject(int idx, Object ob, int type) throws SQLException {
        validate();
        statement.setObject(idx, ob, type);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param ob the object value
     * @param type the type from <code>java.sql.Types</code>
     * @param scale the scale of the value
     * @throws java.sql.SQLException a database error occurred
     * @see java.sql.Types
     */
    public void setObject(int idx, Object ob, int type, int scale)
        throws SQLException {
        validate();
        statement.setObject(idx, ob, type, scale);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param sec the query timeout in seconds
     * @throws java.sql.SQLException a database error occurred
     */
    public void setQueryTimeout(int sec) throws SQLException {
        validate();
        statement.setQueryTimeout(sec);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param ref the reference value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setRef(int idx, Ref ref) throws SQLException {
        validate();
        statement.setRef(idx, ref);
    }
    
    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param s the short value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setShort(int idx, short s) throws SQLException {
        validate();
        statement.setShort(idx, s);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param str the string value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setString(int idx, String str) throws SQLException {
        validate();
        statement.setString(idx, str);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param t the time value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setTime(int idx, Time t) throws SQLException {
        validate();
        statement.setTime(idx, t);
    }

     /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param t the time value
     * @param cal the calendar for the time value
     * @throws java.sql.SQLException a database error occurred
     */
   public void setTime(int idx, Time t, Calendar cal) throws SQLException {
        validate();
        statement.setTime(idx, t, cal);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param ts the timestamp value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setTimestamp(int idx, Timestamp ts) throws SQLException {
        validate();
        statement.setTimestamp(idx, ts);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param ts the timestamp value
     * @param cal the calendar for the tiemstamp value
     * @throws java.sql.SQLException a database error occurred
     */
    public void setTimestamp(int idx, Timestamp ts, Calendar cal)
        throws SQLException {
        validate();
        statement.setTimestamp(idx, ts, cal);
    }

    /**
     * Delegates to the underlying prepared statement.
     * @param idx the index to assign a value for
     * @param is the input stream
     * @param len the length of the input stream
     * @throws java.sql.SQLException a database error occurred
     * @deprecated use setCharacterStream()
     */
    public void setUnicodeStream(int idx, InputStream is, int len)
        throws SQLException {
        validate();
        statement.setUnicodeStream(idx, is, len);
    }

    /**
     * Verifies that this statement is still valid.
     * @throws java.sql.SQLException the statement is no longer valid
     */
    private void validate() throws SQLException {
        if( isClosed() ) {
            throw new SQLException("Illegal attempt to access statement.");
        }
    }

    public String toString() {
        if( statement != null ) {
            return super.toString() + " [" + statement.toString() + "]";
        }
        else {
            return super.toString();
        }
    }
}