net.sourceforge.pbeans.data
Class AbstractDatabase

java.lang.Object
  extended by net.sourceforge.pbeans.data.AbstractDatabase
All Implemented Interfaces:
Database
Direct Known Subclasses:
GenericDatabase

public abstract class AbstractDatabase
extends java.lang.Object
implements Database

Base implementation of Database. This class implements common functionalilty in order to allow fairly straight-forward Database implementations by simply extending this class and overriding some methods.


Nested Class Summary
protected  class AbstractDatabase.TypeInfo
           
 
Field Summary
protected  int sqlStateType
           
 
Constructor Summary
AbstractDatabase()
          Constructs an AbstractDatabase.
 
Method Summary
protected  int autoIncrementColumnNumber()
          Returns the column number of the auto-increment value found in the result set of the query provided by getAutoIncrementRetrievalStatement.
protected  java.lang.String autoIncrementDeclaration()
          Override to provide field declaration qualifier for auto-increment fields.
 void beginTransaction(int transactionIsolationLevel)
          Begins a transaction.
protected  boolean canSetNullableOnTableAlter()
          Determines if the database is able to alter existing fields such that their nullable status changes (and the change is reflected in database metadata.) This implementation returns true by default.
 void endTransaction(boolean rollback)
          Ends a transaction.
 void ensureTableExists(java.lang.String tableName, FieldDescriptor mandatoryField, java.util.Collection fieldDescriptors, java.util.Collection indexDescriptors)
          Makes sure that a table exists.
 void ensureTableExists(java.lang.String tableName, FieldDescriptor mandatoryField, java.util.Collection fieldDescriptors, java.util.Collection indexDescriptors, boolean userManaged, boolean autoIncrementRequested, boolean deleteFields)
          Creates a table if necessary.
protected abstract  java.sql.PreparedStatement getAutoIncrementRetrievalStatement(java.sql.Connection c)
          Gets a PreparedStatement instance that can be used to retrieve the auto-increment value of a record just inserted.
 java.lang.String getAutomaticPrimaryKeyIndexName()
          Gets the name of an implicit index created when there's a primary, as reported in database metadata.
protected  ResultsIterator<BeanWrapper> getBeanIterator(net.sourceforge.pbeans.data.ConnectionPool.ConnectionWrapper conn, java.sql.ResultSet resultSet, BeanUnmarshaller unmarshaller)
          Given a ResultSet, this method returns an iterator of BeanWrapper's.
protected  BeanWrapper getBeanWrapper(java.sql.ResultSet resultSet, BeanUnmarshaller unmarshaller, java.lang.String idField)
          Converts current ResultSet data into a BeanWrapper.
protected abstract  java.sql.PreparedStatement[] getChangeFieldStatements(java.sql.Connection c, java.lang.String tableName, FieldDescriptor fd, boolean autoIncrement)
          Gets a sequence of Statements that can modify a field's type and whether it's nullable.
protected  net.sourceforge.pbeans.data.ConnectionPool.ConnectionWrapper getConnectionWrapper()
          Gets a connection wrapper from the internal connection pool.
protected  java.sql.PreparedStatement[] getCreateFieldStatements(java.sql.Connection c, java.lang.String normalTableName, FieldDescriptor fd, boolean autoIncrement)
          Gets a Statement that adds a field to a table.
protected  java.sql.PreparedStatement[] getCreateIndexStatements(java.sql.Connection c, java.lang.String tableName, IndexDescriptor id, java.util.Map<java.lang.String,FieldDescriptor> normalFieldMap)
          Gets a sequence of Statements that create one index.
protected  java.sql.PreparedStatement getCreateTableStatement(java.sql.Connection c, java.lang.String tableName, FieldDescriptor fd, boolean autoIncrementRequested)
          Gets a Statement that creates a table with a single field.
protected  java.sql.PreparedStatement[] getDropIndexStatements(java.sql.Connection c, java.lang.String tableName, java.lang.String name)
          Gets a sequence of Statements that remove one index.
 int getMaxColumnNameLength()
          Gets the maximum length of a column name in this database.
 int getMaxTableNameLength()
          Gets the maximum length of a table name.
protected  java.sql.PreparedStatement getRemoveFieldStatement(java.sql.Connection c, java.lang.String tableName, java.lang.String columnName)
          Gets a Statement that removes a field.
protected abstract  java.sql.PreparedStatement[] getRenameFieldStatements(java.sql.Connection c, java.lang.String tableName, java.lang.String oldName, FieldDescriptor fd, boolean autoIncrement)
          Gets a sequence of Statements that can rename a field.
protected  java.lang.Object getResultSetValue(int i, java.lang.String name, int type, java.sql.ResultSet resultSet)
          Gets an object from the ResultSet.
protected  java.lang.String getTypeDeclaration(int dataType)
          Gets the type declaration for a type constant as defined in java.sql.Types.
 void init(javax.sql.DataSource dataSource)
          Override this method to obtain metadata information, such as the JDBC URL.
protected  void initDatabaseInfo()
          Initializes some meta-information about the database, particularly about supported types.
 java.lang.Long insert(java.lang.String tableName, java.lang.String idField, java.lang.String[] normalFieldNames, java.lang.Object[] values, boolean autoIncrementRequested)
          Inserts a record in a table.
 boolean inTransaction()
          Determines if the current thread is executing within a transaction.
protected  boolean isBlob(int type)
           
protected  boolean isDecimal(int type)
           
abstract  boolean isDuplicateEntryError(java.sql.SQLException se)
          Determines if the SQLException given corresponds to a duplicate record error (such as one given when you try to insert a record with a unique index that already exists.)
protected  boolean isLong(int type)
           
protected  boolean isText(int type)
           
protected  boolean isTiny(int type)
           
protected  IndexDescriptor normalizeIndex(java.lang.String normalTableName, IndexDescriptor id)
          Override this method if the database has special requirements on index names, such as global uniqueness or lowercase strings.
 java.lang.String normalizeName(java.lang.String s)
          Takes a field name or table name as it would be requested by a caller and coverts it to a string as it would be reported by database metadata (for example, as lowercase strings, in some databases.) Override this method if the database has special naming requirements for field or table names.
 ResultsIterator<BeanWrapper> query(java.lang.String sql, java.lang.Object[] parameters, BeanUnmarshaller unmarshaller)
          Queries the database.
protected  void releaseConnectionWrapper(net.sourceforge.pbeans.data.ConnectionPool.ConnectionWrapper wrapper)
           
 void relinquishLock(boolean rollback)
          If the matching call to requestLock requested a transaction, this method ends it, and also relinquishes the Java lock.
 void requestLock(java.lang.String lockStr, int transactionIsolationLevel)
          Requests a Java thread lock, in addition to starting a transaction, if not already in one.
protected  boolean requiresKeyLength()
          Determines whether the database requires a key length qualifier for indexes on text fields.
 void rollback(java.sql.Savepoint savepoint)
           
 void setConnectionTimeout(int timeout)
          Sets the amount of time, in milliseconds, that a pooled connection may be idle before it is discarded.
 void setMaxConnections(int maxConnections)
          Sets the maximum number of simultaneous open connections.
protected  void setParameter(java.sql.PreparedStatement ps, int index, java.lang.Object objVal)
          Sets a PrepartedStatement parameter.
 java.sql.Savepoint setSavepoint(java.lang.String savepointName)
           
 boolean shouldCloseConnectionAfterTransaction()
          Determines if the database connection should be closed after a commit.
protected  boolean supportsAutoIncrement()
          Determines if the database supports auto-increment primary keys.
protected  boolean typesMatch(int type1, int type2)
          Checks whether two SQL types match when trying to determine if a field declaration should be changed.
 int update(java.lang.String sql, java.lang.Object[] parameters)
          Executes an insert or update operation in the database.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

sqlStateType

protected int sqlStateType
Constructor Detail

AbstractDatabase

public AbstractDatabase()
                 throws java.sql.SQLException
Constructs an AbstractDatabase.

Throws:
java.sql.SQLException
See Also:
GenericDataSource
Method Detail

init

public void init(javax.sql.DataSource dataSource)
          throws java.sql.SQLException
Override this method to obtain metadata information, such as the JDBC URL. Implementations for "odbc" and "datadirect" should override this. Note that the override must invoke the super implementation.

Specified by:
init in interface Database
Parameters:
dataSource - A DataSource instance.
Throws:
java.sql.SQLException

setMaxConnections

public final void setMaxConnections(int maxConnections)
Sets the maximum number of simultaneous open connections.


setConnectionTimeout

public final void setConnectionTimeout(int timeout)
Sets the amount of time, in milliseconds, that a pooled connection may be idle before it is discarded.


getMaxTableNameLength

public int getMaxTableNameLength()
                          throws java.sql.SQLException
Gets the maximum length of a table name. This information is obtained from database metadata. There should be no need to override this method.

Specified by:
getMaxTableNameLength in interface Database
Throws:
java.sql.SQLException

getMaxColumnNameLength

public final int getMaxColumnNameLength()
                                 throws java.sql.SQLException
Gets the maximum length of a column name in this database. This information is obtained from database metadata. There should be no need to override this method.

Specified by:
getMaxColumnNameLength in interface Database
Throws:
java.sql.SQLException

initDatabaseInfo

protected void initDatabaseInfo()
                         throws java.sql.SQLException
Initializes some meta-information about the database, particularly about supported types. There should be no need to override this method.

Throws:
java.sql.SQLException

getTypeDeclaration

protected java.lang.String getTypeDeclaration(int dataType)
                                       throws java.sql.SQLException
Gets the type declaration for a type constant as defined in java.sql.Types. By default, type declarations are populated from metadata. If this information is not accurate, override this method.

Throws:
java.sql.SQLException

isDuplicateEntryError

public abstract boolean isDuplicateEntryError(java.sql.SQLException se)
Determines if the SQLException given corresponds to a duplicate record error (such as one given when you try to insert a record with a unique index that already exists.)

Specified by:
isDuplicateEntryError in interface Database

ensureTableExists

public void ensureTableExists(java.lang.String tableName,
                              FieldDescriptor mandatoryField,
                              java.util.Collection fieldDescriptors,
                              java.util.Collection indexDescriptors)
                       throws java.sql.SQLException
Makes sure that a table exists. There should be no need to override this method.

Parameters:
tableName - The name of the table.
mandatoryField - Information about the mandatory (primary key) field.
fieldDescriptors - Information about other fields.
indexDescriptors - Information about indexes.
Throws:
java.sql.SQLException

getAutomaticPrimaryKeyIndexName

public java.lang.String getAutomaticPrimaryKeyIndexName()
Gets the name of an implicit index created when there's a primary, as reported in database metadata. If no such index is reported, this method returns null. Override if the create table statement is sufficient to create a primary key which need not be created explicitly.


ensureTableExists

public void ensureTableExists(java.lang.String tableName,
                              FieldDescriptor mandatoryField,
                              java.util.Collection fieldDescriptors,
                              java.util.Collection indexDescriptors,
                              boolean userManaged,
                              boolean autoIncrementRequested,
                              boolean deleteFields)
                       throws java.sql.SQLException
Creates a table if necessary. First, it makes sure field names don't match any reserved database keywords. Then, it removes table fields not found in fieldDescriptors. It adds any new fields, and changes types of existing fields if needed. Finally, it modifies and creates requested indexes. There should be no need to override this method.

Specified by:
ensureTableExists in interface Database
Parameters:
tableName - Name of the table.
mandatoryField - A FieldDescriptor which cannot be removed later (typically the table's primary key.)
fieldDescriptors - A collection of FieldDescriptor instances.
indexDescriptors - A collection of IndexDescriptor instances.
autoIncrementRequested - Whether auto-increment is requested for mandatory field.
deleteFields - Whether fields not requested that were found in the table should be deleted.
Throws:
java.sql.SQLException

normalizeName

public java.lang.String normalizeName(java.lang.String s)
Takes a field name or table name as it would be requested by a caller and coverts it to a string as it would be reported by database metadata (for example, as lowercase strings, in some databases.) Override this method if the database has special naming requirements for field or table names.

Specified by:
normalizeName in interface Database

canSetNullableOnTableAlter

protected boolean canSetNullableOnTableAlter()
Determines if the database is able to alter existing fields such that their nullable status changes (and the change is reflected in database metadata.) This implementation returns true by default. Override if the database is unable to alter fields in this manner.


normalizeIndex

protected IndexDescriptor normalizeIndex(java.lang.String normalTableName,
                                         IndexDescriptor id)
Override this method if the database has special requirements on index names, such as global uniqueness or lowercase strings.

Parameters:
normalTableName - A table name, already normalized.
id - An IndexDescriptor instance.

typesMatch

protected boolean typesMatch(int type1,
                             int type2)
Checks whether two SQL types match when trying to determine if a field declaration should be changed. Override this method if pBeans is changing fields to equivalent types unnecessarily.


isLong

protected boolean isLong(int type)

isDecimal

protected boolean isDecimal(int type)

isBlob

protected boolean isBlob(int type)

isText

protected boolean isText(int type)

isTiny

protected boolean isTiny(int type)

getCreateTableStatement

protected java.sql.PreparedStatement getCreateTableStatement(java.sql.Connection c,
                                                             java.lang.String tableName,
                                                             FieldDescriptor fd,
                                                             boolean autoIncrementRequested)
                                                      throws java.sql.SQLException
Gets a Statement that creates a table with a single field. Override this method if the default CREATE syntax does not work.

Throws:
java.sql.SQLException

getRemoveFieldStatement

protected java.sql.PreparedStatement getRemoveFieldStatement(java.sql.Connection c,
                                                             java.lang.String tableName,
                                                             java.lang.String columnName)
                                                      throws java.sql.SQLException
Gets a Statement that removes a field. Override this method if the default ALTER syntax does not work.

Throws:
java.sql.SQLException

getCreateFieldStatements

protected java.sql.PreparedStatement[] getCreateFieldStatements(java.sql.Connection c,
                                                                java.lang.String normalTableName,
                                                                FieldDescriptor fd,
                                                                boolean autoIncrement)
                                                         throws java.sql.SQLException
Gets a Statement that adds a field to a table. Override this method if the default ALTER syntax does not work.

Throws:
java.sql.SQLException

getChangeFieldStatements

protected abstract java.sql.PreparedStatement[] getChangeFieldStatements(java.sql.Connection c,
                                                                         java.lang.String tableName,
                                                                         FieldDescriptor fd,
                                                                         boolean autoIncrement)
                                                                  throws java.sql.SQLException
Gets a sequence of Statements that can modify a field's type and whether it's nullable.

Throws:
java.sql.SQLException

getRenameFieldStatements

protected abstract java.sql.PreparedStatement[] getRenameFieldStatements(java.sql.Connection c,
                                                                         java.lang.String tableName,
                                                                         java.lang.String oldName,
                                                                         FieldDescriptor fd,
                                                                         boolean autoIncrement)
                                                                  throws java.sql.SQLException
Gets a sequence of Statements that can rename a field. The statements should change the field's type and whether the field is nullable.

Throws:
java.sql.SQLException

requiresKeyLength

protected boolean requiresKeyLength()
Determines whether the database requires a key length qualifier for indexes on text fields. The default is false. Override if database requires key lenghts in the text fields of an index.


getCreateIndexStatements

protected java.sql.PreparedStatement[] getCreateIndexStatements(java.sql.Connection c,
                                                                java.lang.String tableName,
                                                                IndexDescriptor id,
                                                                java.util.Map<java.lang.String,FieldDescriptor> normalFieldMap)
                                                         throws java.sql.SQLException
Gets a sequence of Statements that create one index. Override if the default CREATE INDEX syntax does not work.

Parameters:
normalFieldMap - A map from normalized field names to FieldDescriptors.
Throws:
java.sql.SQLException

getDropIndexStatements

protected java.sql.PreparedStatement[] getDropIndexStatements(java.sql.Connection c,
                                                              java.lang.String tableName,
                                                              java.lang.String name)
                                                       throws java.sql.SQLException
Gets a sequence of Statements that remove one index. Override if the default DROP INDEX syntax does not work.

Parameters:
name - The name of the index.
Throws:
java.sql.SQLException

requestLock

public final void requestLock(java.lang.String lockStr,
                              int transactionIsolationLevel)
                       throws java.lang.InterruptedException,
                              java.sql.SQLException
Requests a Java thread lock, in addition to starting a transaction, if not already in one.

Specified by:
requestLock in interface Database
Throws:
java.lang.InterruptedException
java.sql.SQLException

relinquishLock

public final void relinquishLock(boolean rollback)
                          throws java.sql.SQLException
If the matching call to requestLock requested a transaction, this method ends it, and also relinquishes the Java lock.

Specified by:
relinquishLock in interface Database
Throws:
java.sql.SQLException

query

public ResultsIterator<BeanWrapper> query(java.lang.String sql,
                                          java.lang.Object[] parameters,
                                          BeanUnmarshaller unmarshaller)
                                   throws java.sql.SQLException
Queries the database. There should be no need to override this method.

Specified by:
query in interface Database
Parameters:
sql - A SQL SELECT statement with question marks (?) as placeholders.
parameters - An array of parameters whose length is equal to the number of placeholders in the SQL statement.
unmarshaller - A BeanUnmarshaller implementation instance.
Throws:
java.sql.SQLException
See Also:
Database.update(java.lang.String, java.lang.Object[])

update

public int update(java.lang.String sql,
                  java.lang.Object[] parameters)
           throws java.sql.SQLException
Executes an insert or update operation in the database. There should be no need to override this method.

Specified by:
update in interface Database
Parameters:
sql - A SQL modification statement with question marks (?) as placeholders.
parameters - An array of parameters whose length is equal to the number of placeholders in the SQL statement.
Throws:
java.sql.SQLException
See Also:
Database.query(java.lang.String, java.lang.Object[], net.sourceforge.pbeans.data.BeanUnmarshaller)

supportsAutoIncrement

protected boolean supportsAutoIncrement()
Determines if the database supports auto-increment primary keys. This default implementation returns false. Override if the database supports auto-increment fields.


autoIncrementDeclaration

protected java.lang.String autoIncrementDeclaration()
Override to provide field declaration qualifier for auto-increment fields. By default this method returns AUTO_INCREMENT.


getAutoIncrementRetrievalStatement

protected abstract java.sql.PreparedStatement getAutoIncrementRetrievalStatement(java.sql.Connection c)
                                                                          throws java.sql.SQLException
Gets a PreparedStatement instance that can be used to retrieve the auto-increment value of a record just inserted.

Parameters:
c - A Connection instance.
Throws:
java.sql.SQLException

autoIncrementColumnNumber

protected int autoIncrementColumnNumber()
Returns the column number of the auto-increment value found in the result set of the query provided by getAutoIncrementRetrievalStatement. Override if the column number is anything other than 1.


insert

public java.lang.Long insert(java.lang.String tableName,
                             java.lang.String idField,
                             java.lang.String[] normalFieldNames,
                             java.lang.Object[] values,
                             boolean autoIncrementRequested)
                      throws java.sql.SQLException
Inserts a record in a table. There should be no need to override this method.

Specified by:
insert in interface Database
idField - Name of ID field.
autoIncrementRequested - Whether auto-increment is requested for the ID field.
Returns:
The record ID.
Throws:
java.sql.SQLException

setParameter

protected void setParameter(java.sql.PreparedStatement ps,
                            int index,
                            java.lang.Object objVal)
                     throws java.sql.SQLException
Sets a PrepartedStatement parameter. Override if this method or the setObject method of PrepartedStatement are not setting parameter values as expected.

Throws:
java.sql.SQLException

getBeanIterator

protected ResultsIterator<BeanWrapper> getBeanIterator(net.sourceforge.pbeans.data.ConnectionPool.ConnectionWrapper conn,
                                                       java.sql.ResultSet resultSet,
                                                       BeanUnmarshaller unmarshaller)
Given a ResultSet, this method returns an iterator of BeanWrapper's. There should be no need to override this method.


getBeanWrapper

protected BeanWrapper getBeanWrapper(java.sql.ResultSet resultSet,
                                     BeanUnmarshaller unmarshaller,
                                     java.lang.String idField)
                              throws java.sql.SQLException
Converts current ResultSet data into a BeanWrapper. There should be no need to override this method.

Throws:
java.sql.SQLException

getResultSetValue

protected java.lang.Object getResultSetValue(int i,
                                             java.lang.String name,
                                             int type,
                                             java.sql.ResultSet resultSet)
                                      throws java.sql.SQLException
Gets an object from the ResultSet. Override if the ResultSet is not returing an object of the desired type.

Throws:
java.sql.SQLException

getConnectionWrapper

protected net.sourceforge.pbeans.data.ConnectionPool.ConnectionWrapper getConnectionWrapper()
                                                                                     throws java.sql.SQLException
Gets a connection wrapper from the internal connection pool. For transactions to work properly, JDBC connections must be obtained by invoking this method. There should be no need to override this method.

Throws:
java.sql.SQLException

releaseConnectionWrapper

protected void releaseConnectionWrapper(net.sourceforge.pbeans.data.ConnectionPool.ConnectionWrapper wrapper)
                                 throws java.sql.SQLException
Throws:
java.sql.SQLException

beginTransaction

public final void beginTransaction(int transactionIsolationLevel)
                            throws java.sql.SQLException
Begins a transaction.

Specified by:
beginTransaction in interface Database
Throws:
java.sql.SQLException

endTransaction

public final void endTransaction(boolean rollback)
                          throws java.sql.SQLException
Ends a transaction.

Specified by:
endTransaction in interface Database
Throws:
java.sql.SQLException

inTransaction

public final boolean inTransaction()
Determines if the current thread is executing within a transaction.

Specified by:
inTransaction in interface Database

shouldCloseConnectionAfterTransaction

public boolean shouldCloseConnectionAfterTransaction()
Determines if the database connection should be closed after a commit. This default implemetation returns true. Override if a connection where a transaction just occurred can still be used.


setSavepoint

public final java.sql.Savepoint setSavepoint(java.lang.String savepointName)
                                      throws java.sql.SQLException
Specified by:
setSavepoint in interface Database
Throws:
java.sql.SQLException

rollback

public final void rollback(java.sql.Savepoint savepoint)
                    throws java.sql.SQLException
Specified by:
rollback in interface Database
Throws:
java.sql.SQLException