org.geotools.data.jdbc
Class JDBCDataStore

java.lang.Object
  extended byorg.geotools.data.jdbc.JDBCDataStore
All Implemented Interfaces:
DataStore

public abstract class JDBCDataStore
extends java.lang.Object
implements DataStore

Abstract helper class for JDBC DataStore implementations.

This class provides a default implementation of a JDBC data store. Support for vendor specific JDBC data stores can be easily added to Geotools by subclassing this class and overriding the hooks provided.

At a minimum subclasses should implement the following methods:

Additionally subclasses can optionally override the following:

Author:
Sean Geoghegan, Defence Science and Technology Organisation, Chris Holmes, TOPP

Nested Class Summary
static class JDBCDataStore.FeatureTypeInfo
          Stores information about known FeatureTypes.
protected  class JDBCDataStore.JDBCFeatureWriter
           
static class JDBCDataStore.QueryData
          Provides an encapsulation of the connection, statement and result set of a JDBC query.
 
Field Summary
 FeatureListenerManager listenerManager
          Manages listener lists for FeatureSource implementations
protected static java.util.Map TYPE_MAPPINGS
          Maps SQL types to Java classes.
 
Constructor Summary
JDBCDataStore(ConnectionPool connectionPool)
           
JDBCDataStore(ConnectionPool connectionPool, java.lang.String databaseSchemaName)
           
JDBCDataStore(ConnectionPool connectionPool, java.lang.String databaseSchemaName, java.lang.String namespace)
           
 
Method Summary
protected  boolean allowTable(java.lang.String tablename)
          Provides a hook for sub classes to filter out specific tables in the data store that are not to be used as geospatial tables.
protected  java.lang.String[] attributeNames(FeatureType featureType, Filter filter)
          Gets the list of attribute names required for both featureType and filter
protected  AttributeReader[] buildAttributeReaders(AttributeType[] attrTypes, JDBCDataStore.QueryData queryData)
          Builds the AttributeReaders from the QueryData and the array of attribute types.
protected  AttributeType buildAttributeType(java.sql.ResultSet rs)
          Constructs an AttributeType from a row in a ResultSet.
protected  AttributeWriter[] buildAttributeWriters(AttributeType[] attrTypes, JDBCDataStore.QueryData queryData)
           
protected static void close(java.sql.Connection conn, Transaction transaction, java.sql.SQLException sqlException)
          A utility method for closing a Connection.
protected static void close(java.sql.ResultSet rs)
          A utility method for closing a ResultSet.
protected static void close(java.sql.Statement statement)
          A utility method for closing a Statement.
protected  FeatureReader createFeatureReader(FeatureType schema, Filter postFilter, JDBCDataStore.QueryData queryData)
          Create a new FeatureReader based on attributeReaders.
protected  JDBCDataStore.JDBCFeatureWriter createFeatureWriter(FeatureReader fReader, AttributeWriter writer, JDBCDataStore.QueryData queryData)
           
protected abstract  AttributeReader createGeometryReader(AttributeType attrType, JDBCDataStore.QueryData queryData, int index)
          Hook to create the geometry reader for a vendor specific data source.
protected abstract  AttributeWriter createGeometryWriter(AttributeType attrType, JDBCDataStore.QueryData queryData, int index)
           
protected  LockingManager createLockingManager()
          Allows subclass to create LockingManager to support their needs.
protected  AttributeReader createResultSetReader(AttributeType[] attrType, JDBCDataStore.QueryData queryData, int startIndex, int endIndex)
           
protected  AttributeWriter createResultSetWriter(AttributeType[] attrType, JDBCDataStore.QueryData queryData, int startIndex, int endIndex)
           
 void createSchema(FeatureType featureType)
          Create a new featureType.
protected  java.lang.String determineFidColumnName(java.lang.String typeName)
          Provides the default implementation of determining the FID column.
protected  int determineSRID(java.lang.String tableName, java.lang.String geometryColumnName)
          Provides a hook for subclasses to determine the SRID of a geometry column.
protected  JDBCDataStore.QueryData executeQuery(java.lang.String tableName, java.lang.String sqlQuery, Transaction transaction, int concurrency)
          Executes the SQL Query.
protected  AttributeType[] getAttributeTypes(java.lang.String typeName, java.lang.String[] propertyNames)
           
protected  java.sql.Connection getConnection(Transaction transaction)
          Gets a connection from the connection pool.
 FeatureReader getFeatureReader(FeatureType requestType, Filter filter, Transaction transaction)
          This is a public entry point to the DataStore.
 FeatureReader getFeatureReader(Query query, Transaction trans)
          The top level method for getting a FeatureReader.
 FeatureSource getFeatureSource(java.lang.String typeName)
          Default implementation based on getFeatureReader and getFeatureWriter.
protected  JDBCDataStore.FeatureTypeInfo getFeatureTypeInfo(java.lang.String featureTypeName)
          Retreives the FeatureTypeInfo object for a FeatureType.
 FeatureWriter getFeatureWriter(java.lang.String typeName, Filter filter, Transaction transaction)
          Aquire FetureWriter for modification of contents specifed by filter.
 FeatureWriter getFeatureWriter(java.lang.String typeName, Transaction transaction)
          Retrieve a FeatureWriter over entire dataset.
 FeatureWriter getFeatureWriterAppend(java.lang.String typeName, Transaction transaction)
          Retrieve a FeatureWriter for creating new content.
 LockingManager getLockingManager()
          Locking manager used for this DataStore.
 java.lang.String getNameSpace()
          Gets the namespace of the data store.
 FeatureType getSchema(java.lang.String typeName)
          Retrieve FeatureType metadata by typeName.
 SQLBuilder getSqlBuilder(java.lang.String typeName)
          Hook for subclass to return a different sql builder.
 java.lang.String[] getTypeNames()
          Retrieves a list of of the available FeatureTypes
 FeatureSource getView(Query query)
           
 void updateSchema(java.lang.String typeName, FeatureType featureType)
          Used to provide support for changing the DataStore Schema.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

TYPE_MAPPINGS

protected static final java.util.Map TYPE_MAPPINGS
Maps SQL types to Java classes. This might need to be fleshed out more later, Ive ignored complex types such as ARRAY, BLOB and CLOB. It is protected so subclasses can override it I guess.

These mappings were taken from http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/mapping.html#997737


listenerManager

public FeatureListenerManager listenerManager
Manages listener lists for FeatureSource implementations

Constructor Detail

JDBCDataStore

public JDBCDataStore(ConnectionPool connectionPool)
              throws java.io.IOException

JDBCDataStore

public JDBCDataStore(ConnectionPool connectionPool,
                     java.lang.String databaseSchemaName)
              throws java.io.IOException

JDBCDataStore

public JDBCDataStore(ConnectionPool connectionPool,
                     java.lang.String databaseSchemaName,
                     java.lang.String namespace)
              throws java.io.IOException
Method Detail

createLockingManager

protected LockingManager createLockingManager()
Allows subclass to create LockingManager to support their needs.

Returns:

getTypeNames

public java.lang.String[] getTypeNames()
Description copied from interface: DataStore
Retrieves a list of of the available FeatureTypes

This is simply a list of the FeatureType names as aquiring the actual FeatureType schemas may be expensive.

Specified by:
getTypeNames in interface DataStore
Returns:
typeNames for available FeatureTypes.

getSchema

public FeatureType getSchema(java.lang.String typeName)
                      throws java.io.IOException
Description copied from interface: DataStore
Retrieve FeatureType metadata by typeName.

Retrieves the Schema information as a FeatureType object.

Specified by:
getSchema in interface DataStore
Parameters:
typeName - typeName of requested FeatureType
Returns:
FeatureType for the provided typeName
Throws:
java.io.IOException - If typeName cannot be found

createSchema

public void createSchema(FeatureType featureType)
                  throws java.io.IOException
Create a new featureType.

Not currently supported - subclass may implement.

Specified by:
createSchema in interface DataStore
Parameters:
featureType -
Throws:
java.io.IOException
java.lang.UnsupportedOperationException - DOCUMENT ME!
See Also:
DataStore.createSchema(org.geotools.feature.FeatureType)

updateSchema

public void updateSchema(java.lang.String typeName,
                         FeatureType featureType)
                  throws java.io.IOException
Used to provide support for changing the DataStore Schema.

Specifically this is intended to address updating the metadata Coordinate System information.

If we can figure out the Catalog API for metadata we will not have to use such a heavy handed approach.

Subclasses are free to implement various levels of support:

Specified by:
updateSchema in interface DataStore
Parameters:
typeName -
Throws:
java.io.IOException
See Also:
DataStore.updateSchema(java.lang.String, org.geotools.feature.FeatureType)

getView

public FeatureSource getView(Query query)
                      throws java.io.IOException,
                             SchemaException
Throws:
java.io.IOException
SchemaException

getFeatureSource

public FeatureSource getFeatureSource(java.lang.String typeName)
                               throws java.io.IOException
Default implementation based on getFeatureReader and getFeatureWriter.

We should be able to optimize this to only get the RowSet once

Specified by:
getFeatureSource in interface DataStore
Parameters:
typeName -
Returns:
FeatureSource (or subclass) providing opperations for typeName
Throws:
java.io.IOException
See Also:
DataStore.getFeatureSource(java.lang.String)

getFeatureReader

public FeatureReader getFeatureReader(FeatureType requestType,
                                      Filter filter,
                                      Transaction transaction)
                               throws java.io.IOException
This is a public entry point to the DataStore.

We have given some though to changing this api to be based on query.

Currently the is is the only way to retype your features to different name spaces.

(non-Javadoc)

Specified by:
getFeatureReader in interface DataStore
Parameters:
requestType - Describes the form of the returned Features
filter - Constraints used to limit the results
transaction - Transaction this query opperates against
Returns:
FeatureReader Allows Sequential Processing of featureType
Throws:
java.io.IOException
See Also:
DataStore.getFeatureReader(org.geotools.feature.FeatureType, org.geotools.filter.Filter, org.geotools.data.Transaction)

attributeNames

protected java.lang.String[] attributeNames(FeatureType featureType,
                                            Filter filter)
                                     throws java.io.IOException
Gets the list of attribute names required for both featureType and filter

Parameters:
featureType - DOCUMENT ME!
filter - DOCUMENT ME!
Returns:
DOCUMENT ME!
Throws:
java.io.IOException - DOCUMENT ME!

getFeatureReader

public FeatureReader getFeatureReader(Query query,
                                      Transaction trans)
                               throws java.io.IOException
The top level method for getting a FeatureReader.

Chris- I've gone with the Query object aswell. It just seems to make more sense. This is pretty well split up across methods. The hooks for DB specific AttributeReaders are createResultSetReader and createGeometryReader.

JG- I have implemented getFeatureReader( FeatureType, Filter, Transasction) ontop of this method, it will Retype as required

Parameters:
query -
trans -
Returns:
Throws:
java.io.IOException - DOCUMENT ME!
DataSourceException

createFeatureReader

protected FeatureReader createFeatureReader(FeatureType schema,
                                            Filter postFilter,
                                            JDBCDataStore.QueryData queryData)
                                     throws java.io.IOException
Create a new FeatureReader based on attributeReaders.

The provided schema describes the attributes in the queryData ResultSet. This schema should cover the requirements of filter.

Retyping to the users requested Schema will not happen in this method.

Parameters:
schema -
postFilter - Filter for post processing, or null if not requried.
queryData - Holds a ResultSet for attribute Readers
Returns:
Throws:
java.io.IOException
DataSourceException - DOCUMENT ME!

buildAttributeReaders

protected final AttributeReader[] buildAttributeReaders(AttributeType[] attrTypes,
                                                        JDBCDataStore.QueryData queryData)
                                                 throws java.io.IOException
Builds the AttributeReaders from the QueryData and the array of attribute types. This is private since the default implementation shoud not need to be overriden.

Subclasses can provide custom attribute readers for the basic types by overriding createResultSetReader(). createResultSetReader has parameters that define a range of columns in the Result to read. The default implementation of this method creates a RangedResultSetAttributeReader instance.

Subclasses must provide a geometry attribute reader by implementing createGeometryReader(). This must provide an AttributeReader capable of reading a geometry at a single column. This will be called when isGeometry() on a attribute returns true.

TODO: Should this be final??

Parameters:
attrTypes - The attribute types to create a list of AttributeReaders for.
queryData - The Query result resources for the readers.
Returns:
The list of attribute readers.
Throws:
java.io.IOException - If an error occurs building the readers. It seems to make sense that if we can't get readers for all the attribute we shoudl bomb out. (??)

executeQuery

protected final JDBCDataStore.QueryData executeQuery(java.lang.String tableName,
                                                     java.lang.String sqlQuery,
                                                     Transaction transaction,
                                                     int concurrency)
                                              throws java.io.IOException
Executes the SQL Query.

This is private in the expectation that subclasses should not need to change this behaviour.

Jody with a question here - I have stopped this method from closing connection shared by a Transaction. It sill seems like we are leaving connections open by using this method. I have also stopped QueryData from doing the same thing.

Answer from Sean: Resources for successful queries are closed when close is called on the AttributeReaders constructed with the QueryData. We can't close them here since they need to be open to read from the ResultSet.

Jody AttributeReader question: I looked at the code and Attribute Readers do not close with respect to Transactions (they need to as we can issue a Reader against a Transaction. I have changed the JDBCDataStore.close method to force us to keep track of these things.

SG: I've marked this as final since I don't think it shoudl be overriden, but Im not sure

Parameters:
tableName - DOCUMENT ME!
sqlQuery - The SQL query to execute.
transaction - The Transaction is included here for handling transaction connections at a later stage. It is not currently used.
concurrency - DOCUMENT ME!
Returns:
The QueryData object that contains the resources for the query.
Throws:
java.io.IOException - DOCUMENT ME!
DataSourceException - If an error occurs performing the query.

getSqlBuilder

public SQLBuilder getSqlBuilder(java.lang.String typeName)
                         throws java.io.IOException
Hook for subclass to return a different sql builder.

Parameters:
typeName - The typename for the sql builder.
Returns:
A new sql builder.
Throws:
java.io.IOException - if anything goes wrong.

createResultSetReader

protected AttributeReader createResultSetReader(AttributeType[] attrType,
                                                JDBCDataStore.QueryData queryData,
                                                int startIndex,
                                                int endIndex)

createResultSetWriter

protected AttributeWriter createResultSetWriter(AttributeType[] attrType,
                                                JDBCDataStore.QueryData queryData,
                                                int startIndex,
                                                int endIndex)

createGeometryReader

protected abstract AttributeReader createGeometryReader(AttributeType attrType,
                                                        JDBCDataStore.QueryData queryData,
                                                        int index)
                                                 throws java.io.IOException
Hook to create the geometry reader for a vendor specific data source.

Parameters:
attrType - The AttributeType to read.
queryData - The data containing the result of the query.
index - The index within the result set to read the data from.
Returns:
The AttributeReader that will read the geometry from the results.
Throws:
DataSourceException - If an error occurs building the AttributeReader.
java.io.IOException

createGeometryWriter

protected abstract AttributeWriter createGeometryWriter(AttributeType attrType,
                                                        JDBCDataStore.QueryData queryData,
                                                        int index)
                                                 throws java.io.IOException
Throws:
java.io.IOException

getConnection

protected final java.sql.Connection getConnection(Transaction transaction)
                                           throws java.io.IOException
Gets a connection from the connection pool.

Parameters:
transaction - DOCUMENT ME!
Returns:
A single use connection.
Throws:
java.io.IOException - DOCUMENT ME!
DataSourceException - If the connection is not an OracleConnection.

close

protected static void close(java.sql.Connection conn,
                            Transaction transaction,
                            java.sql.SQLException sqlException)
A utility method for closing a Connection. Wraps and logs any exceptions thrown by the close method.

Connections are maintained by a Transaction and we will need to manage them with respect to their Transaction.

Jody here - I am forcing this to be explicit, by requiring you give the Transaction context when you close a connection seems to be the only way to hunt all the cases down. AttributeReaders based on QueryData rely on

I considered accepting an error flag to control Transaction rollback, but I really only want to capture SQLException that force transaction rollback.

Parameters:
conn - The Connection to close. This can be null since it makes it easy to close connections in a finally block.
transaction - Context for the connection, we will only close the connection for Transaction.AUTO_COMMIT
sqlException - Error status, null for no error

close

protected static void close(java.sql.ResultSet rs)
A utility method for closing a ResultSet. Wraps and logs any exceptions thrown by the close method.

Parameters:
rs - The ResultSet to close. This can be null since it makes it easy to close result sets in a finally block.

close

protected static void close(java.sql.Statement statement)
A utility method for closing a Statement. Wraps and logs any exceptions thrown by the close method.

Parameters:
statement - The statement to close. This can be null since it makes it easy to close statements in a finally block.

allowTable

protected boolean allowTable(java.lang.String tablename)
Provides a hook for sub classes to filter out specific tables in the data store that are not to be used as geospatial tables. The default implementation of this method is to allow all tables.

Parameters:
tablename - A table name to check.
Returns:
True if the table should be exposed as a FeatureType, false if it should be ignored.

buildAttributeType

protected AttributeType buildAttributeType(java.sql.ResultSet rs)
                                    throws java.sql.SQLException,
                                           DataSourceException
Constructs an AttributeType from a row in a ResultSet. The ResultSet contains the information retrieved by a call to getColumns() on the DatabaseMetaData object. This information can be used to construct an Attribute Type.

The default implementation construct an AttributeType using the default JDBC type mappings defined in JDBCDataStore. These type mappings only handle native Java classes and SQL standard column types, so to handle Geometry columns, sub classes should override this to check if a column is a geometry column, if it is a geometry column the appropriate determination of the geometry type can be performed. Otherwise, overriding methods should call super.buildAttributeType.

Note: Overriding methods must never move the current row pointer in the result set.

Parameters:
rs - The ResultSet containing the result of a DatabaseMetaData.getColumns call.
Returns:
The AttributeType built from the ResultSet.
Throws:
java.sql.SQLException - If an error occurs processing the ResultSet.
DataSourceException - Provided for overriding classes to wrap exceptions caused by other operations they may perform to determine additional types. This will only be thrown by the default implementation if a type is present that is not present in the TYPE_MAPPINGS.

determineSRID

protected int determineSRID(java.lang.String tableName,
                            java.lang.String geometryColumnName)
                     throws java.io.IOException
Provides a hook for subclasses to determine the SRID of a geometry column.

This allows SRIDs to be determined in a Vendor specific way and to be cached by the default implementation. To retreive these srids, get the FeatureTypeInfo object for the table and call getSRID(geometryColumnName). This will allow storage of SRIDs for multiple geometry columns in each table.

If no SRID can be found, subclasses should return -1. The default implementation always returns -1.

Parameters:
tableName - The name of the table to get the SRID for.
geometryColumnName - The name of the geometry column within the table to get SRID for.
Returns:
The SRID for the geometry column in the table or -1.
Throws:
java.io.IOException - DOCUMENT ME!

determineFidColumnName

protected java.lang.String determineFidColumnName(java.lang.String typeName)
                                           throws java.io.IOException
Provides the default implementation of determining the FID column.

The default implementation of determining the FID column name is to use the primary key as the FID column. If no primary key is present, null will be returned. Sub classes can override this behaviour to define primary keys for vendor specific cases.

There is an unresolved issue as to what to do when there are multiple primary keys. Maybe a restriction that table much have a single column primary key is appropriate.

This should not be called by subclasses to retreive the FID column name. Instead, subclasses should call getFeatureTypeInfo(String) to get the FeatureTypeInfo for a feature type and get the fidColumn name from the fidColumn name memeber.

Parameters:
typeName - The name of the table to get a primary key for.
Returns:
The name of the primay key column or null if one does not exist.
Throws:
java.io.IOException - This will only occur if there is an error getting a connection to the Database.

getNameSpace

public java.lang.String getNameSpace()
Gets the namespace of the data store.

Returns:
The namespace.

getFeatureTypeInfo

protected final JDBCDataStore.FeatureTypeInfo getFeatureTypeInfo(java.lang.String featureTypeName)
                                                          throws java.io.IOException
Retreives the FeatureTypeInfo object for a FeatureType.

This allows subclasses to get access to the information about a feature type, this includes the schema and the fidColumnName.

Parameters:
featureTypeName - The name of the feature type to get the info for.
Returns:
The FeatureTypeInfo object for the named feature type or null if the feature type does not exist.
Throws:
java.io.IOException - If an error occurs creating the FeatureTypeInfo.

getFeatureWriter

public FeatureWriter getFeatureWriter(java.lang.String typeName,
                                      Transaction transaction)
                               throws java.io.IOException
Retrieve a FeatureWriter over entire dataset.

Quick notes: This FeatureWriter is often used to add new content, or perform summary calculations over the entire dataset.

Subclass may wish to implement an optimized featureWriter for these operations.

It should provide Feature for next() even when hasNext() is false.

Subclasses are responsible for checking with the lockingManger unless they are providing their own locking support.

Specified by:
getFeatureWriter in interface DataStore
Parameters:
typeName -
transaction -
Returns:
Throws:
java.io.IOException
java.lang.UnsupportedOperationException - DOCUMENT ME!
See Also:
org.geotools.data.DataStore#getFeatureWriter(java.lang.String, boolean, org.geotools.data.Transaction)

getFeatureWriterAppend

public FeatureWriter getFeatureWriterAppend(java.lang.String typeName,
                                            Transaction transaction)
                                     throws java.io.IOException
Retrieve a FeatureWriter for creating new content.

Subclass may wish to implement an optimized featureWriter for this operation. One based on prepaired statemnts is a possibility, as we do not require a ResultSet.

To allow new content the FeatureWriter should provide Feature for next() even when hasNext() is false.

Subclasses are responsible for checking with the lockingManger unless they are providing their own locking support.

Specified by:
getFeatureWriterAppend in interface DataStore
Parameters:
typeName -
transaction -
Returns:
Throws:
java.io.IOException
java.lang.UnsupportedOperationException - DOCUMENT ME!
See Also:
org.geotools.data.DataStore#getFeatureWriter(java.lang.String, boolean, org.geotools.data.Transaction)

getFeatureWriter

public FeatureWriter getFeatureWriter(java.lang.String typeName,
                                      Filter filter,
                                      Transaction transaction)
                               throws java.io.IOException
Aquire FetureWriter for modification of contents specifed by filter.

Quick notes: This FeatureWriter is often used to remove contents specified by the provided filter, or perform summary calculations.

It is not used to provide new content and should return null for next() when hasNext() returns false.

Subclasses are responsible for checking with the lockingManger unless they are providing their own locking support.

Specified by:
getFeatureWriter in interface DataStore
Parameters:
typeName -
filter -
transaction -
Returns:
Throws:
java.io.IOException - If typeName could not be located
java.lang.NullPointerException - If the provided filter is null
DataSourceException - See IOException
See Also:
DataStore.getFeatureWriter(java.lang.String, org.geotools.filter.Filter, org.geotools.data.Transaction)

createFeatureWriter

protected JDBCDataStore.JDBCFeatureWriter createFeatureWriter(FeatureReader fReader,
                                                              AttributeWriter writer,
                                                              JDBCDataStore.QueryData queryData)
                                                       throws java.io.IOException
Throws:
java.io.IOException

buildAttributeWriters

protected final AttributeWriter[] buildAttributeWriters(AttributeType[] attrTypes,
                                                        JDBCDataStore.QueryData queryData)
                                                 throws java.io.IOException
Throws:
java.io.IOException

getAttributeTypes

protected AttributeType[] getAttributeTypes(java.lang.String typeName,
                                            java.lang.String[] propertyNames)
                                     throws java.io.IOException,
                                            SchemaException
Throws:
java.io.IOException
SchemaException

getLockingManager

public LockingManager getLockingManager()
Locking manager used for this DataStore.

By default AbstractDataStore makes use of InProcessLockingManager.

Specified by:
getLockingManager in interface DataStore
Returns:
See Also:
DataStore.getLockingManager()


Copyright © 1996-2003 GeoTools. All Rights Reserved.