Database package
Introduction
This package implements a simple framework to work with a database over JDBC. The idea of this simple framework is to write fast robust code.
Design
The DatabaseManager
This class supports an additional abstraction. The DatabaseManager holds
an instance of the DataSource. The idea of the the DatabaseManager
is to work with SQLProcessor's.

A class which implements the SQLProcessor
interface defines a specific SQL statement which can be get with the method getStatement. Each
SQLProcess also implements the processing of the JDBC ResultSet. After the
execution of a SQLProcessor an Object array is returned. The SQL parameters
can be set outside of the SQLProcessor class with the method setStatmentValues.
The sort order of the Object array correspond to the SQL parameter order.
The control over a transaction with a SQLProcessor is part of the DatabaseManager
which works together with a TransactionMonitor (more details see in the
transaction chapter).
The class AbstractSQLProcessor implements the main method of the SQLProcessor
interface. Each subclass of the class AbstractSelectSQLProcessor has also to define the SQL
statment (by calling the method setSQLStatement) and has to implement the method
process which implements the processing of the data. The ResultSet will
closed after process method!
The sequence diagram below shows the connection between the database classes:

There is a simple a select example:
(IMPORTANT: SQLProcessor can be generated by the ProcessorGenerator class from a given SQL code)
public class TestSelectProcessor extends AbstractSelectSQLProcessor
{
/**
* Constructor
*/
public TestSelectProcessor()
{
setSQLStatement( "select address from usertable where username like '?'" );
}
/**
* Returns the data
* @return the read data
*/
protected Object[] process( ResultSet rs )
throws SQLException
{
List data = new ArrayList();
String message;
while( rs.next() )
{
message = rs.getString( 1 );
data.add( message );
}
return data.toArray( new String[ data.size() ] );
}
}
There is a simple insert example:
public class TestInsertProcessor extends AbstractUpdateSQLProcessor
{
/**
* Constructor
*/
public TestInsertProcessor()
{
setSQLStatement( "insert into address (username) values (?)" );
}
}
There next examples show the initialisation of the DatabaseManager and the
the use of it:
Initialisation of the
DatabaseManagerwith theDatabasePoolManager:... FileManager fileManager = new BootManager( new PropertiesManager() ); config = new DatabaseConfig( (Properties)fileManager.getFile("databasetest.properties") ); DatabaseManager dbManager = new DatabaseManager( new DatabasePoolManager( config ) ); ... Object[] param = new Object[1]; param[0] = new String( "myName" ); dbManager.executeQuery( new TestInsertProcessor(), null ); ...Initialisation of the
DatabaseManagerwith aDataSource:... String dataSourceName = "..."; Context ctx = new InitialContext(); DataSource dataSource = (DataSource)ctx.lookup( dataSourceName ); DatabaseManager dbManager = new DatabaseManager( dataSource ); ... Object[] param = new Object[1]; param[0] = new String( "myName" ); dbManager.executeQuery( new TestInsertProcessor(), null ); ...Initialisation of the
DatabaseManagerwith aDataSource. The lookup works with theServiceLocator:... String dataSourceName = "..."; ServiceLocator localtor = new ServiceLocator(); DataSource dataSource = localtor.getDataSource( dataSourceName ); DatabaseManager dbManager = new DatabaseManager( dataSource ); ... Object[] param = new Object[1]; param[0] = new String( "myName" ); dbManager.executeQuery( new TestInsertProcessor(), null ); ...
The BatchProcessor
The class BatchProcessor implements a processor which contains multiple processors which
can executed in one transaction context (more details see in the transaction chapter).
The return value contains a list with the result of each processor (a list with
Object arrays!). If one processor fails then the connection will rollback.
The method addSQLProcessor adds a new SQLProcessor with the execution
values (null if the statement has no values). The execution order of the processors is the same they are added
with the method addSQLProcessor.
There is an example:
...
String createTestTable = "create table jptoolsTest( name varchar(10), theDate date )";
String insertNameToTestTable = "insert into jptoolsTest( NAME ) values( ? )";
BatchSQLProcessor batch = new BatchSQLProcessor( "Batch Execution", null );
batch.addSQLProcessor( new TestSQLProcessor( createTestTable ), null );
batch.addSQLProcessor( new TestInsertSQLProcessor( insertNameToTestTable ), new Object[] { "jptools1" } );
batch.addSQLProcessor( new TestInsertSQLProcessor( insertNameToTestTable ), new Object[] { "jptools2" } );
batch.addSQLProcessor( new TestInsertSQLProcessor( insertNameToTestTable ), new Object[] { "jptools3" } );
List result = manager.executeBatch( batch );
...
Transactions
The DatabaseManager use a TransactionMonitor to control a transaction which starts
and close a transaction. Each processor defines the result values of the execution. If the defined values
do not match with the result of the execution of the processor a defined error message will logged and a rollback
will done. Only if the expected result values match the data processing will commited.
The method setExpectedResult of a processor defines the expected result values and the error message
if the values do not match. The default value is set to null which informs the
DatabaseManager to not control the result values of the processor.
The framework currently implements the following transaction monitors:
jptools.database.SimpleTransactionMonitorjptools.j2ee.database.BMTransactionMonitorjptools.j2ee.database.CMTransactionMonitor
The DatabaseManager class use as default the SimpleTransactionMonitor except an other the
transaction monitor is set in the constructor. An other possibility to use a different transaction monitor
is to hand over a transaction monitor by each executeQuery or executeBatch method call.
There is an example:
...
String createTestTable = "create table jptoolsTest( name varchar(10), theDate date )";
String insertNameToTestTable = "insert into jptoolsTest( NAME ) values( ? )";
BatchSQLProcessor batch = new BatchSQLProcessor( "Batch Execution", null );
batch.addSQLProcessor( new TestSQLProcessor( createTestTable ), null );
batch.addSQLProcessor( new TestInsertSQLProcessor( insertNameToTestTable ), new Object[] { "jptools1" } );
batch.addSQLProcessor( new TestInsertSQLProcessor( insertNameToTestTable ), new Object[] { "jptools2" } );
batch.addSQLProcessor( new TestInsertSQLProcessor( insertNameToTestTable ), new Object[] { "jptools3" } );
UserTransaction ut = context.getUserTransaction(); // context = SessionContext
List result = manager.executeBatch( new BMTransactionMonitor( ut ),
batch );
...
The DataSource DatabasePoolManager
This class implements a simple JDBC connection pooling. It implements the DataSource
interface. Each call of the method
getConnection returns a valid JDBC Connection. The class
Connection extends the SQL Connection. Itself holds a
real Connection to the database. After calling close on the
connection the connection will not real closed. The Connection will pushed
back to the ConnectionStack which is under control of the
DatabasePoolManager.

Configuration
The class DatabaseConfig defines the database configuration like the database
url to connect, the user, the password. In the table below the key and default values are described.
There are some example configuration:
- Oracle (over SQL*Net) (
classes12.zipor 9.2 and greaterojdbc14.jar)database.driver = oracle.jdbc.driver.OracleDriver database.url = jdbc:oracle:oci8:/@SID
- Oracle (Type 4 driver) (
classes12.zipor 9.2 and greaterojdbc14.jar)database.driver = oracle.jdbc.driver.OracleDriver database.url = jdbc:oracle:thin:@server:1521:SID database.username = myUser database.password = myPassword
- MySql
database.driver = com.mysql.jdbc.Driver database.url = jdbc:mysql://server/databaseName database.username = myUser database.password = myPassword
- DB2 (
db2jcc.jaranddb2jcc_license_cu.jar)database.driver = com.ibm.db2.jcc.DB2Driver database.url = jdbc:db2://server:50000/databaseName database.username = myUser database.password = myPassword
- Microsoft SQL Server (
msbase.jar,mssqlserver.jarandmsutil.jar)database.driver = com.microsoft.jdbc.sqlserver.SQLServerDriver database.url = jdbc:microsoft:sqlserver://server:1433;DatabaseName=databaseName;SelectMethod=Cursor database.username = myUser database.password = myPassword
- Microsoft Access
database.driver = sun.jdbc.odbc.JdbcOdbcDriver database.url = jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=directory\\filename.mdb;}
Key |
Default value |
Description |
||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
The jdbc driver of the database. |
|||||||||||||||
|
The jdbc url. |
|||||||||||||||
|
The username of the database to connect to. |
|||||||||||||||
|
The password of the database user. |
|||||||||||||||
|
|
This timeout defines the interval how long the pool should wait of a retry if the creation of a connection was failed. |
||||||||||||||
|
|
The min. connections to the database. After initializing the
|
||||||||||||||
|
|
The max. connections to the database. If this number of connection is
reached and a |
||||||||||||||
|
|
This defines the timeout of a free |
||||||||||||||
|
|
Defines the interval to cleanup the connections in the pool. |
||||||||||||||
|
|
Defines the behavior to shrink the connections in the pool. The following
keys are valid:
|
||||||||||||||
|
|
Switch to log database statistics when something in the connection pool changes. |
||||||||||||||
|
|
Switch to log the database configuration by initializing the DatabasePoolManager. |
||||||||||||||
|
|
Sets the verbose mode. |