net.java.ao
Class PoolProvider

java.lang.Object
  extended by net.java.ao.DatabaseProvider
      extended by net.java.ao.PoolProvider
Direct Known Subclasses:
C3P0PoolProvider, DBCPPoolProvider, DBPoolProvider, ProxoolPoolProvider

public abstract class PoolProvider
extends DatabaseProvider

Abstract superclass for connection pool library abstractions. This class handles some of the grunt work for implementing a connection pool provider, such as returning null for getDriverClass() and delegating interesting methods to the database-specific provider.

Author:
Daniel Spiewak

Constructor Summary
protected PoolProvider(DatabaseProvider delegate)
          Creates a new instance with the given delegate provider.
 
Method Summary
 void dispose()
          Should release all resources held by the pool.
 DatabaseProvider getDelegate()
          Retrieves the delegate DatabaseProvider instnace to which most interesting calls are passed.
 Class<? extends Driver> getDriverClass()
          Returns the JDBC Driver class which corresponds to the database being abstracted.
 ResultSet getTables(Connection conn)
          Returns a result set of all of the tables (and associated meta) in the database.
<T> T
insertReturningKey(Connection conn, Class<T> pkType, String pkField, boolean pkIdentity, String table, DBParam... params)
          Generates an INSERT statement to be used to create a new row in the database, returning the primary key value.
 Object parseValue(int type, String value)
          Parses the database-agnostic String value relevant to the specified SQL type in int form (as defined by Types and returns the Java value which corresponds.
 void putNull(PreparedStatement stmt, int index)
          TODO
 String[] renderAction(DDLAction action)
          Top level delegating method for the process of rendering a database-agnostic DDLAction into the database-specific DDL statement(s).
protected  String renderAutoIncrement()
          Generates the DDL fragment required to specify an INTEGER field as auto-incremented.
 String renderQuery(Query query, TableNameConverter converter, boolean count)
          Top level delegating method for rendering a database-agnostic Query object into its (potentially) database-specific query statement.
protected  void setPostConnectionProperties(Connection conn)
          Called to make any post-creation modifications to a new Connection instance.
 void setQueryResultSetProperties(ResultSet res, Query query)
          Allows the provider to set database-specific options on a ResultSet instance prior to its use by the library.
 void setQueryStatementProperties(Statement stmt, Query query)
          Allows the provider to set database-specific options on a Statement instance prior to its usage in a SELECT query.
 
Methods inherited from class net.java.ao.DatabaseProvider
considerPrecision, convertTypeToString, executeInsertReturningKey, getConnection, getConnectionImpl, getDateFormat, getFunctionNameForField, getInstance, getInstance, getPassword, getTriggerNameForField, getURI, getUsername, isNumericType, renderAlterTableAddColumn, renderAlterTableAddKey, renderAlterTableChangeColumn, renderAlterTableChangeColumnStatement, renderAlterTableDropColumn, renderAlterTableDropKey, renderAppend, renderCalendar, renderConstraintsForTable, renderCreateIndex, renderDropFunctions, renderDropIndex, renderDropSequences, renderDropTable, renderDropTriggers, renderField, renderFieldPrecision, renderFieldType, renderForeignKey, renderFunction, renderFunctionForField, renderFunctions, renderOnUpdate, renderQueryGroupBy, renderQueryJoins, renderQueryLimit, renderQueryOrderBy, renderQuerySelect, renderQueryWhere, renderSequences, renderTable, renderTriggerForField, renderTriggers, renderUnique, renderValue
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

PoolProvider

protected PoolProvider(DatabaseProvider delegate)
Creates a new instance with the given delegate provider. By convention, all pool providers declare a public constructor. However, this convention is not enforced, hence the protected status of this superclass constructor.

Parameters:
delegate - The DatabaseProvider instance to which most interesting method calls should be delegated (such as rendering and schema retrieval).
Method Detail

getDriverClass

public Class<? extends Driver> getDriverClass()
                                       throws ClassNotFoundException
Description copied from class: DatabaseProvider

Returns the JDBC Driver class which corresponds to the database being abstracted. This should be implemented in such a way as to initialize and register the driver with JDBC. For most drivers, this requires code in the following form:

public Class<? extends Driver> getDriverClass() {
     return (Class<? extends Driver>) Class.forName("com.mysql.jdbc.Driver");
 }

The following does not fire the driver's static initializer and thus will (usually) not work:

public Class<? extends Driver> getDriverClass() {
     return com.mysql.jdbc.Driver.class;
 }

If the driver is not on the classpath, a ClassNotFoundException can and should be thrown (certain auto-magic configuration sections of ActiveObjects depend upon this under certain circumstances).

Specified by:
getDriverClass in class DatabaseProvider
Returns:
null
Throws:
ClassNotFoundException

getDelegate

public final DatabaseProvider getDelegate()
Retrieves the delegate DatabaseProvider instnace to which most interesting calls are passed. This cannot be overridden by subclasses, for no particularlly good reason.


parseValue

public Object parseValue(int type,
                         String value)
Description copied from class: DatabaseProvider

Parses the database-agnostic String value relevant to the specified SQL type in int form (as defined by Types and returns the Java value which corresponds. This method is completely database-agnostic, as are all of all of its delegate methods.

WARNING: This method is being considered for removal to another class (perhaps TypeManager?) as it is not a database-specific function and thus confuses the purpose of this class. Do not rely upon it heavily. (better yet, don't rely on it at all from external code. It's not designed to be part of the public API)

Overrides:
parseValue in class DatabaseProvider
Parameters:
type - The JDBC integer type of the database field against which to parse the value.
value - The database-agnostic String value to parse into a proper Java object with respect to the specified SQL type.
Returns:
A Java value which corresponds to the specified String.
See Also:
DatabaseProvider.parseValue(int, String)

renderAction

public String[] renderAction(DDLAction action)
Description copied from class: DatabaseProvider
Top level delegating method for the process of rendering a database-agnostic DDLAction into the database-specific DDL statement(s). It is doubtful that any implementations will have to override this method as the default implementation is database-agnostic.

Overrides:
renderAction in class DatabaseProvider
Parameters:
action - The database-agnostic action to render.
Returns:
An array of DDL statements specific to the database in question.
See Also:
DatabaseProvider.renderAction(DDLAction)

renderQuery

public String renderQuery(Query query,
                          TableNameConverter converter,
                          boolean count)
Description copied from class: DatabaseProvider

Top level delegating method for rendering a database-agnostic Query object into its (potentially) database-specific query statement. This method invokes the various renderQuery* methods to construct its output, thus it is doubtful that any subclasses will have to override it. Rather, one of the delegate methods should be considered.

An example of a database-specific query rendering would be the following Query:

Query.select().from(Person.class).limit(10)

On MySQL, this would render to SELECT id FROM people LIMIT 10 However, on SQL Server, this same Query would render as SELECT TOP 10 id FROM people

Overrides:
renderQuery in class DatabaseProvider
Parameters:
query - The database-agnostic Query object to be rendered in a potentially database-specific way.
converter - Used to convert Entity classes into table names.
count - If true, render the Query as a SELECT COUNT(*) rather than a standard field-data query.
Returns:
A syntactically complete SQL statement potentially specific to the database.
See Also:
DatabaseProvider.renderQuery(Query, TableNameConverter, boolean)

setQueryStatementProperties

public void setQueryStatementProperties(Statement stmt,
                                        Query query)
                                 throws SQLException
Description copied from class: DatabaseProvider

Allows the provider to set database-specific options on a Statement instance prior to its usage in a SELECT query. This is to allow things like emulation of the LIMIT feature on databases which don't support it within the SQL implementation.

This method is only called on SELECTs.

Overrides:
setQueryStatementProperties in class DatabaseProvider
Parameters:
stmt - The instance against which the properties should be set.
query - The query which is being executed against the statement instance.
Throws:
SQLException
See Also:
DatabaseProvider.setQueryStatementProperties(Statement, Query)

setQueryResultSetProperties

public void setQueryResultSetProperties(ResultSet res,
                                        Query query)
                                 throws SQLException
Description copied from class: DatabaseProvider
Allows the provider to set database-specific options on a ResultSet instance prior to its use by the library. This allows for features such as row offsetting even on databases that don't support it (such as Oracle, Derby, etc).

Overrides:
setQueryResultSetProperties in class DatabaseProvider
Parameters:
res - The ResultSet to modify.
query - The query instance which was run to produce the result set.
Throws:
SQLException
See Also:
DatabaseProvider.setQueryResultSetProperties(ResultSet, Query)

getTables

public ResultSet getTables(Connection conn)
                    throws SQLException
Description copied from class: DatabaseProvider

Returns a result set of all of the tables (and associated meta) in the database. The fields of the result set must correspond with those specified in the DatabaseMetaData#getTables(String, String, String, String[]) method. In fact, the default implementation meerly calls this method passing (null, null, "", null). For databases (such as PostgreSQL) where this is unsuitable, different parameters can be specified to the getTables method in the override, or an entirely new implementation written, as long as the result set corresponds in fields to the JDBC spec.

Databases which do not support this function (such as Oracle) should not throw an exception. Instead, they should print a warning to stderr and return null. ActiveObjects will interpret a null result set as signifying no tables in the database, usually leading to a complete recreation of the schema (raw migration).

Overrides:
getTables in class DatabaseProvider
Parameters:
conn - The connection to use in retrieving the database tables.
Returns:
A result set of tables (and meta) corresponding in fields to the JDBC specification.
Throws:
SQLException
See Also:
DatabaseProvider.getTables(Connection)

insertReturningKey

public <T> T insertReturningKey(Connection conn,
                                Class<T> pkType,
                                String pkField,
                                boolean pkIdentity,
                                String table,
                                DBParam... params)
                     throws SQLException
Description copied from class: DatabaseProvider

Generates an INSERT statement to be used to create a new row in the database, returning the primary key value. This method also invokes the delegate method, DatabaseProvider.executeInsertReturningKey(Connection, Class, String, String, DBParam...) passing the appropriate parameters and query. This method is required because some databases do not support the JDBC parameter RETURN_GENERATED_KEYS (such as HSQLDB and PostgreSQL). Also, some databases (such as MS SQL Server) require odd tricks to support explicit value passing to auto-generated fields. This method should take care of any extra queries or odd SQL generation required to implement both auto-generated primary key returning, as well as explicit primary key value definition.

Overriding implementations of this method should be sure to use the Connection instance passed to the method, not a new instance generated using the DatabaseProvider.getConnection() method. This is because this method is in fact a delegate invoked by EntityManager as part of the entity creation process and may be part of a transaction, a bulk creation or some more complicated operation. Both optimization and usage patterns on the API dictate that the specified connection instance be used. Implementations may assume that the given connection instance is never null.

The default implementation of this method should be sufficient for any fully compliant ANSI SQL database with a properly implemented JDBC driver. Note that this method should not not actually execute the SQL it generates, but pass it on to the DatabaseProvider.executeInsertReturningKey(Connection, Class, String, String, DBParam...) method, allowing for functional delegation and better extensibility. However, this method may execute any additional statements required to prepare for the INSERTion (as in the case of MS SQL Server which requires some config parameters to be set on the database itself prior to INSERT).

Overrides:
insertReturningKey in class DatabaseProvider
Parameters:
conn - The connection to be used in the eventual execution of the generated SQL statement.
pkType - The Java type of the primary key value. Can be used to perform a linear search for a specified primary key value in the params list. The return value of the method must be of the same type.
pkField - The database field which is the primary key for the table in question. Can be used to perform a linear search for a specified primary key value in the params list.
pkIdentity - Flag indicating whether or not the primary key field is auto-incremented by the database (IDENTITY field).
table - The name of the table into which the row is to be INSERTed.
params - A varargs array of parameters to be passed to the INSERT statement. This may include a specified value for the primary key.
Throws:
SQLException - If the INSERT fails in the delegate method, or if any additional statements fail with an exception.
See Also:
DatabaseProvider.insertReturningKey(Connection, Class, String, boolean, String, DBParam...)

putNull

public void putNull(PreparedStatement stmt,
                    int index)
             throws SQLException
Description copied from class: DatabaseProvider
TODO

Overrides:
putNull in class DatabaseProvider
Throws:
SQLException

setPostConnectionProperties

protected void setPostConnectionProperties(Connection conn)
                                    throws SQLException
Description copied from class: DatabaseProvider
Called to make any post-creation modifications to a new Connection instance. This is used for databases such as Derby which require the schema to be set after the connection is created.

Overrides:
setPostConnectionProperties in class DatabaseProvider
Parameters:
conn - The connection to modify according to the database requirements.
Throws:
SQLException

renderAutoIncrement

protected String renderAutoIncrement()
Description copied from class: DatabaseProvider

Generates the DDL fragment required to specify an INTEGER field as auto-incremented. For databases which do not support such flags (which is just about every database exception MySQL), "" is an acceptable return value. This method should never return null as it would cause the field rendering method to throw a NullPointerException.

This method is abstract (as opposed to the other methods which are either defined against MySQL or simply empty) because of the vast differences in rendering auto-incremented fields across different databases. Also, it seemed like a terribly good idea at the time and I haven't found a compelling reason to change it.

Specified by:
renderAutoIncrement in class DatabaseProvider

dispose

public void dispose()

Should release all resources held by the pool. This is especially important to implement for pool providers, as conection pools may have connections which are being held (potentially) indefinitely. It is important for developers to call this method to free resources, as well as it is important for custom implementation authors to implement the method to perform such a function.

Implementations should take the following form:

public void dispose() {
     connectionPool.freeAllConnections();
     
     super.dispose();
 }

This method additionally delegates its call to the delegate provider instance, ensuring that (for databases which require it) database resources are appropriately freed.

Overrides:
dispose in class DatabaseProvider
See Also:
DatabaseProvider.dispose()