You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2007/01/12 19:19:45 UTC
svn commit: r495677 [3/9] - in /db/ojb/trunk: ./ profile/
src/java/org/apache/ojb/broker/ src/java/org/apache/ojb/broker/accesslayer/
src/java/org/apache/ojb/broker/accesslayer/batch/
src/java/org/apache/ojb/broker/accesslayer/sql/ src/java/org/apache/...
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/StatementManagerImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/StatementManagerImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/StatementManagerImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/StatementManagerImpl.java Fri Jan 12 10:19:39 2007
@@ -31,11 +31,16 @@
import org.apache.ojb.broker.platforms.Platform;
import org.apache.ojb.broker.platforms.PlatformException;
import org.apache.ojb.broker.util.SqlHelper;
+import org.apache.ojb.broker.util.ExceptionHelper;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
/**
- * Manages the JDBC-Statement resources.
+ * Manages the JDBC-Statement resources. This class is responsible to create statements
+ * and to cleanup used resources like statements and result sets.
+ * <br/>
+ * Additionally this implementation supports a simple statement cache (without wrapping
+ * or "proxying" the used {@link java.sql.Connection} and {@link java.sql.Statement}).
*
* @version $Id$
*/
@@ -43,13 +48,17 @@
{
private Logger log = LoggerFactory.getLogger(StatementManagerImpl.class);
+ protected final static short STMT_TYPE_PREPARED = 2;
+ protected final static short STMT_TYPE_CALLABLE = 3;
+ protected final static short STMT_TYPE_NORMAL = 4;
+
/** the associated broker */
protected final PersistenceBrokerInternal broker;
protected final Platform platform;
protected final ConnectionManagerIF connectionManager;
/** force use of JDBC 1.0 statement creation */
- protected boolean FORCEJDBC1_0 = false;
+ protected boolean forceJdbc_1_0 = false;
/** Global fetch size, set in {@link org.apache.ojb.broker.metadata.ConnectionFactoryDescriptor}. */
protected final int fetchSize;
@@ -71,26 +80,34 @@
statementCache = new StatementBuffer(maxCachedStatements);
// detect JDBC level
double level = connectionManager.getConnectionDescriptor().getJdbcLevel();
- FORCEJDBC1_0 = level == 1.0;
+ forceJdbc_1_0 = level == 1.0;
}
public void closeResources(Statement stmt, ResultSet rs)
{
- Statement tmpStmt = stmt;
if(useStatementCache && statementCache.containsValue(stmt))
{
- tmpStmt = null;
+ // don't close the cached statement
+ internalCloseResources(null, rs);
+ }
+ else
+ {
+ internalCloseResources(stmt, rs);
}
+ }
+
+ void internalCloseResources(Statement stmt, ResultSet rs)
+ {
try
{
- platform.beforeStatementClose(tmpStmt, rs);
+ platform.beforeStatementClose(stmt, rs);
//close statement on wrapped statement class, or real statement
- if(tmpStmt != null)
+ if(stmt != null)
{
- if(log.isDebugEnabled()) log.debug("close used statement: " + tmpStmt);
- tmpStmt.close();
+ if(log.isDebugEnabled()) log.debug("close used statement: " + stmt);
+ stmt.close();
}
- platform.afterStatementClose(tmpStmt, rs);
+ platform.afterStatementClose(stmt, rs);
}
catch(PlatformException e)
{
@@ -105,6 +122,11 @@
public void beforeConnectionRelease()
{
+ clearStatementCache();
+ }
+
+ protected void clearStatementCache()
+ {
if(statementCache.size() > 0)
{
boolean old = useStatementCache;
@@ -115,7 +137,7 @@
while(it.hasNext())
{
it.next();
- closeResources((PreparedStatement) it.getValue(), null);
+ internalCloseResources((PreparedStatement) it.getValue(), null);
it.remove();
}
}
@@ -134,7 +156,11 @@
{
try
{
- return prepareStatement(connectionManager.getConnection(), sql, scrollable, callableStmt, explicitFetchSizeHint);
+ return (PreparedStatement) prepareStatement(
+ sql,
+ scrollable,
+ callableStmt ? STMT_TYPE_CALLABLE : STMT_TYPE_PREPARED,
+ explicitFetchSizeHint);
}
catch(SQLException ex)
{
@@ -156,14 +182,14 @@
}
/**
- * return a generic Statement for the given ClassDescriptor.
+ * Return a generic Statement for the given ClassDescriptor.
* Never use this method for UPDATE/INSERT/DELETE if you want to use the batch mode.
*/
public Statement getGenericStatement(boolean scrollable) throws PersistenceBrokerException
{
try
{
- return createStatement(connectionManager.getConnection(), scrollable,
+ return prepareStatement(null, scrollable, STMT_TYPE_NORMAL,
StatementManager.FETCH_SIZE_NOT_EXPLICITLY_SET);
}
catch(SQLException ex)
@@ -181,195 +207,155 @@
/**
* Prepares a statement with parameters that should work with most RDBMS.
*
- * @param con the connection to utilize
* @param sql the sql syntax to use when creating the statement.
* @param scrollable determines if the statement will be scrollable.
- * @param callableStmt if <code>false</code>, then a {@link java.sql.PreparedStatement}
- * will be created. If <code>true</code>, then a {@link java.sql.CallableStatement} will be created.
+ * @param stmtType The type of the statement, see {@link #STMT_TYPE_CALLABLE},
+ * {@link #STMT_TYPE_PREPARED}, {@link #STMT_TYPE_NORMAL}.
* @param explicitFetchSizeHint will be used as fetchSize hint
* (if applicable) if > 0
* @return a statement that can be used to execute the syntax contained in
* the <code>sql</code> argument.
*/
- protected PreparedStatement prepareStatement(Connection con,
- String sql,
+ protected Statement prepareStatement(String sql,
boolean scrollable,
- boolean callableStmt,
- int explicitFetchSizeHint) throws SQLException
+ short stmtType,
+ int explicitFetchSizeHint) throws SQLException, LookupException
{
- PreparedStatement result;
+ final Connection con = connectionManager.getConnection();
+ Statement result = null;
- if(useStatementCache && !callableStmt)
+ if(useStatementCache && stmtType != STMT_TYPE_NORMAL)
{
result = statementCache.getStatement(sql, scrollable, explicitFetchSizeHint);
- if(result != null)
+ if(result != null && !(result.getConnection() == con))
{
- return result;
+ result = null;
}
}
-
- // if a JDBC1.0 driver is used the signature
- // prepareStatement(String, int, int) is not defined.
- // we then call the JDBC1.0 variant prepareStatement(String)
- try
+ if(result == null)
{
- // if necessary use JDB1.0 methods
- if(!FORCEJDBC1_0)
+ // if a JDBC1.0 driver is used the signature
+ // prepareStatement(String, int, int) is not defined.
+ // we then call the JDBC1.0 variant prepareStatement(String)
+ try
{
- if(!callableStmt)
+ // if necessary use JDB1.0 methods
+ if(!forceJdbc_1_0)
{
- result =
- con.prepareStatement(
- sql,
- scrollable
- ? ResultSet.TYPE_SCROLL_INSENSITIVE
- : ResultSet.TYPE_FORWARD_ONLY,
- ResultSet.CONCUR_READ_ONLY);
- performFetchSizeSetting(result, explicitFetchSizeHint);
-
- // add statement to cache
- if(useStatementCache) statementCache.addStatement(sql, result, scrollable);
+ result = jdbcVersionTwoStatement(con, sql, scrollable, stmtType, explicitFetchSizeHint);
+ performFetchSizeSetting(result, explicitFetchSizeHint, sql);
}
else
{
- result =
- con.prepareCall(
- sql,
- scrollable
- ? ResultSet.TYPE_SCROLL_INSENSITIVE
- : ResultSet.TYPE_FORWARD_ONLY,
- ResultSet.CONCUR_READ_ONLY);
+ result = jdbcVersionOneStatement(con, sql, stmtType);
}
}
- else
+ catch(AbstractMethodError err)
{
- if(callableStmt)
+ // this exception is raised if Driver is not JDBC 2.0 compliant
+ log.warn("Used driver seems not JDBC 2.0 compatible, use the JDBC 1.0 mode", err);
+ result = jdbcVersionOneStatement(con, sql, stmtType);
+ forceJdbc_1_0 = true;
+ }
+ catch(SQLException eSql)
+ {
+ // there are JDBC Driver that nominally implement JDBC 2.0, but
+ // throw DriverNotCapableExceptions. If we catch one of these
+ // we force usage of JDBC 1.0
+ if(eSql
+ .getClass()
+ .getName()
+ .equals("interbase.interclient.DriverNotCapableException"))
{
- result = con.prepareStatement(sql);
-
- // add statement to cache
- if(useStatementCache) statementCache.addStatement(sql, result, scrollable);
+ log.warn("JDBC 2.0 problems with this interbase driver, we use the JDBC 1.0 mode");
+ result = jdbcVersionOneStatement(con, sql, stmtType);
+ forceJdbc_1_0 = true;
}
else
{
- result = con.prepareCall(sql);
+ throw eSql;
}
}
- }
- catch(AbstractMethodError err)
- {
- // this exception is raised if Driver is not JDBC 2.0 compliant
- log.warn("Used driver seems not JDBC 2.0 compatible, use the JDBC 1.0 mode", err);
- if(callableStmt)
- {
- result = con.prepareStatement(sql);
- }
- else
+ try
{
- result = con.prepareCall(sql);
+ platform.afterStatementCreate(result);
}
- FORCEJDBC1_0 = true;
- }
- catch(SQLException eSql)
- {
- // there are JDBC Driver that nominally implement JDBC 2.0, but
- // throw DriverNotCapableExceptions. If we catch one of these
- // we force usage of JDBC 1.0
- if(eSql
- .getClass()
- .getName()
- .equals("interbase.interclient.DriverNotCapableException"))
+ catch(PlatformException e)
{
- log.warn("JDBC 2.0 problems with this interbase driver, we use the JDBC 1.0 mode");
- if(callableStmt)
- {
- result = con.prepareStatement(sql);
- }
- else
- {
- result = con.prepareCall(sql);
- }
- FORCEJDBC1_0 = true;
- }
- else
- {
- throw eSql;
+ log.error("Platform dependend failure after create of new statement", e);
}
}
- try
- {
- platform.afterStatementCreate(result);
- }
- catch(PlatformException e)
- {
- log.error("Platform dependend failure", e);
- }
return result;
}
- /** Creates a statement with parameters that should work with most RDBMS. */
- protected Statement createStatement(Connection con, boolean scrollable, int explicitFetchSizeHint) throws SQLException
+ protected Statement jdbcVersionTwoStatement(final Connection con,
+ final String sql,
+ final boolean scrollable,
+ final short stmtType,
+ final int explicitFetchSizeHint) throws SQLException
{
- Statement result;
+ final Statement result;
try
{
- // if necessary use JDBC1.0 methods
- if(!FORCEJDBC1_0)
+ if(stmtType == STMT_TYPE_PREPARED)
{
- result =
- con.createStatement(
- scrollable
- ? ResultSet.TYPE_SCROLL_INSENSITIVE
- : ResultSet.TYPE_FORWARD_ONLY,
- ResultSet.CONCUR_READ_ONLY);
- performFetchSizeSetting(result, explicitFetchSizeHint);
+ result = con.prepareStatement( sql,
+ scrollable ? ResultSet.TYPE_SCROLL_INSENSITIVE : ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY);
+ performFetchSizeSetting(result, fetchSize, sql);
+ // add statement to cache
+ if(useStatementCache) statementCache.addStatement(sql, result, scrollable);
+ }
+ else if(stmtType == STMT_TYPE_CALLABLE)
+ {
+ result = con.prepareCall(sql,
+ scrollable ? ResultSet.TYPE_SCROLL_INSENSITIVE : ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY);
+ performFetchSizeSetting(result, fetchSize, sql);
+ // add statement to cache
+ if(useStatementCache) statementCache.addStatement(sql, result, scrollable);
}
else
{
- result = con.createStatement();
+ result = con.createStatement(
+ scrollable ? ResultSet.TYPE_SCROLL_INSENSITIVE : ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY);
}
}
- catch(AbstractMethodError err)
+ catch(SQLException e)
{
- // if a JDBC1.0 driver is used, the signature
- // createStatement(int, int) is not defined.
- // we then call the JDBC1.0 variant createStatement()
- log.warn("Used driver seems not JDBC 2.0 compatible, use the JDBC 1.0 mode", err);
- result = con.createStatement();
- FORCEJDBC1_0 = true;
+ String msg = ExceptionHelper.generateMessage("Statement creation failed", e, sql);
+ log.error(msg);
+ throw e;
}
- catch(SQLException eSql)
+ return result;
+ }
+
+ protected Statement jdbcVersionOneStatement(final Connection con,
+ final String sql,
+ final short stmtType) throws SQLException
+ {
+ final Statement result;
+ if(stmtType == STMT_TYPE_PREPARED)
{
- // there are JDBC Driver that nominally implement JDBC 2.0, but
- // throw DriverNotCapableExceptions. If we catch one of these
- // we force usage of JDBC 1.0
- if(eSql
- .getClass()
- .getName()
- .equals("interbase.interclient.DriverNotCapableException"))
- {
- log.warn("JDBC 2.0 problems with this interbase driver, we use the JDBC 1.0 mode");
- FORCEJDBC1_0 = true;
- result = con.createStatement();
- }
- else
- {
- throw eSql;
- }
+ result = con.prepareStatement(sql);
+ // add statement to cache
+ if(useStatementCache) statementCache.addStatement(sql, result, false);
}
- try
+ else if(stmtType == STMT_TYPE_CALLABLE)
{
- platform.afterStatementCreate(result);
+ result = con.prepareCall(sql);
+ // add statement to cache
+ if(useStatementCache) statementCache.addStatement(sql, result, false);
}
- catch(PlatformException e)
+ else
{
- log.error("Platform dependend failure", e);
+ result = con.createStatement();
}
return result;
}
- private void performFetchSizeSetting(Statement stmt, int explicitFetchSizeHint)
- throws SQLException
+ private void performFetchSizeSetting(final Statement stmt, final int explicitFetchSizeHint, final String sql)
{
if(stmt != null)
{
@@ -384,11 +370,22 @@
}
else
{
- fetchSizeHint = fetchSize; // connection pool default
+ fetchSizeHint = fetchSize; // configured default setting
}
- if(fetchSizeHint > 0)
+ try
{
- stmt.setFetchSize(fetchSize);
+ if(fetchSizeHint > 0)
+ {
+ stmt.setFetchSize(fetchSize);
+ }
+ else if(useStatementCache) // guarantee that cached stmt will use default fetch size setting
+ {
+ stmt.setFetchSize(StatementManager.FETCH_SIZE_NOT_EXPLICITLY_SET);
+ }
+ }
+ catch(SQLException e)
+ {
+ log.warn("Can't set fetch size '" + fetchSize + "' on statement for query: " + sql);
}
}
}
@@ -401,6 +398,15 @@
public void setUseStatementCache(boolean useStatementCache)
{
this.useStatementCache = useStatementCache;
+ if(!useStatementCache && statementCache.size() > 0)
+ {
+ clearStatementCache();
+ }
+ }
+
+ public Platform getPlatform()
+ {
+ return platform;
}
//===================================================================
@@ -415,27 +421,19 @@
super(max);
}
- void addStatement(String sql, PreparedStatement stmt, boolean scrollable)
+ void addStatement(String sql, Statement stmt, boolean scrollable)
{
// important to differ if the sql should be scrollable or not, thus
// append the result at the end of the sql key string
super.put(sql + BooleanUtils.toStringTrueFalse(scrollable), stmt);
}
- PreparedStatement getStatement(String sql, boolean scrollable, int fetchSize)
+ Statement getStatement(String sql, boolean scrollable, int fetchSize)
{
// important to differ if the sql should be scrollable or not, thus
// append the result at the end of the sql key string
- PreparedStatement result = (PreparedStatement) super.get(sql + BooleanUtils.toStringTrueFalse(scrollable));
- try
- {
- // allow to set fetch size for statement
- performFetchSizeSetting(result, fetchSize);
- }
- catch(SQLException e)
- {
- log.error("Can't set fetch size '" + fetchSize + "' on statement for query: " + sql);
- }
+ Statement result = (Statement) super.get(sql + BooleanUtils.toStringTrueFalse(scrollable));
+ performFetchSizeSetting(result, fetchSize, sql);
return result;
}
@@ -445,17 +443,8 @@
*/
protected boolean removeLRU(LinkEntry linkEntry)
{
- boolean old = useStatementCache;
- useStatementCache = false;
- try
- {
- closeResources((PreparedStatement) linkEntry.getValue(), null);
- return super.removeLRU(linkEntry);
- }
- finally
- {
- useStatementCache = old;
- }
+ internalCloseResources((Statement) linkEntry.getValue(), null);
+ return super.removeLRU(linkEntry);
}
}
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchListener.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchListener.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchListener.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchListener.java Fri Jan 12 10:19:39 2007
@@ -18,22 +18,21 @@
/**
* Makes possible to hock up in batch process.
*
- * @author <a href="mailto:arminw@apache.org">Armin Waibel</a>
* @version $Id$
*/
public interface BatchListener
{
/**
- * Called before the {@link BatchEntity} was executed.
+ * Called before the {@link Batcher} was executed.
* @param entity The entity the {@link BatchManager} work on.
*/
- void beforeBatchExecution(BatchEntity entity);
+ void beforeBatchExecution(Batcher entity);
/**
- * Called after the {@link BatchEntity} was executed. If an exception occurs
+ * Called after the {@link Batcher} was executed. If an exception occurs
* while batch entry execution, this method will be skipped.
*
* @param entity The entity the {@link BatchManager} work on.
*/
- void afterBatchExecution(BatchEntity entity);
+ void afterBatchExecution(Batcher entity);
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchManager.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchManager.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchManager.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchManager.java Fri Jan 12 10:19:39 2007
@@ -31,24 +31,26 @@
/**
* Add values to batch.
*
- * @param info The metadata of the batch statement.
+ * @param batcher The batch metadata and values.
* @param values An array of {@link ValueContainer} representing the object
* or database row to batch.
* @param expectedResult The expected {@link java.sql.Statement} return
* value (number of modified rows).
* @throws SQLException
*/
- public void addToBatch(BatchInfo info, ValueContainer[] values, int expectedResult) throws SQLException;
+ public void add(Batcher batcher, ValueContainer[] values, int expectedResult) throws SQLException;
- /** Execute all hold out batch statements. */
+ /**
+ * Execute all hold out batch statements.
+ */
public void executeBatch() throws PersistenceBrokerException;
/**
- * Execute batch on given {@link BatchEntity}.
+ * Execute batch on given {@link Batcher}.
*
- * @param entity The {@link BatchEntity} to execute.
+ * @param batcher The {@link Batcher} to execute.
*/
- public void executeBatch(BatchEntity entity) throws PersistenceBrokerException;
+ public void executeBatch(Batcher batcher) throws PersistenceBrokerException;
/**
* Discard all batched statements and close all resources without
@@ -57,17 +59,13 @@
public void cancelBatch();
/**
- * Creates a new {@link BatchEntity} instance.
- *
- * @param descriptor An {@link BatchInfo} encapsulates meta info of the batch statement.
- * @return a new create batch entity.
+ * Add an {@link BatchListener} object.
*/
- public BatchEntity createEntity(BatchInfo descriptor);
-
- /** Add an {@link BatchListener} object. */
public void addBatchListener(BatchListener listener);
- /** Removes an {@link BatchListener} object. */
+ /**
+ * Removes an {@link BatchListener} object.
+ */
public void removeBatchListener(BatchListener listener);
/**
@@ -128,13 +126,19 @@
*/
public boolean getBatchSupportOptimisticLocking();
- /** Set the batch limit. */
+ /**
+ * Set the batch limit.
+ */
public void setBatchLimit(int limit);
- /** Get the batch limit. */
+ /**
+ * Get the batch limit.
+ */
public int getBatchLimit();
- /** Returns the used {@link BatchStrategy}. */
+ /**
+ * Returns the used {@link BatchStrategy}.
+ */
public BatchStrategy getStrategy();
/**
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchManagerImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchManagerImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchManagerImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchManagerImpl.java Fri Jan 12 10:19:39 2007
@@ -26,6 +26,7 @@
import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
import org.apache.ojb.broker.platforms.Platform;
import org.apache.ojb.broker.util.ExceptionHelper;
+import org.apache.ojb.broker.util.IdentityArrayList;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
@@ -42,7 +43,7 @@
* <td><strong>Property Values</strong></td>
* </tr>
* <tr>
- * <td>batch.includeOptimisticLocking</td>
+ * <td>batch.supportOptimisticLocking</td>
* <td>
* To support optimistic locking within batch mode the used jdbc-driver have to return
* the number of affected rows for each batched statement, see {@link java.sql.PreparedStatement#executeBatch()}.
@@ -57,7 +58,6 @@
* </tr>
* </table>
*
- * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
* @version $Id$
*/
public class BatchManagerImpl implements BatchManager
@@ -69,7 +69,6 @@
protected ReturnValueValidator validator;
private static final String BATCH_INCLUDE_OPTIMISTIC_LOCKING_PROPERTY_STR = "batch.supportOptimisticLocking";
- private static final BatchListener[] NULL_LISTENER = new BatchListener[0];
private int batchLimit = 50;
private int batchLimitCounter;
private boolean batchMode;
@@ -87,7 +86,10 @@
* can be set <em>true</em> to optimize the batch handling for objects with optimistic locking enabled.
*/
private boolean batchSupportOptimisticLocking;
- private BatchListener[] batchListener = NULL_LISTENER;
+ /**
+ * Object identity based list to register {@link BatchListener}.
+ */
+ private List batchListener = new IdentityArrayList();
private List batchEntities = new ArrayList();
public BatchManagerImpl(PersistenceBrokerInternal broker, ReturnValueValidator validator)
@@ -132,66 +134,20 @@
this.strategy = strategy;
}
- /** @see BatchManager#createEntity */
- public BatchEntity createEntity(BatchInfo descriptor)
- {
- return new BatchEntity(this, descriptor);
- }
-
- public void addToBatch(BatchInfo info, ValueContainer[] values, int expectedResult) throws SQLException
+ public void executeBatch(Batcher batcher)
{
- if(checkBatchLimit())
- {
- if(log.isEnabledFor(Logger.INFO))
- {
- log.info("Batch limit reached, execute batch before add new batch entry");
- }
- executeBatch();
- }
-
- BatchEntity entity = findEntity(info);
- if(entity == null)
- {
- // create new entity
- entity = new BatchEntity(this, info);
- if(log.isDebugEnabled()) log.debug("Create new BatchEntity: " + entity);
- // lookup batch strategy and ask for updated (reordered, reduced, ...)
- // list of batch entities
- batchEntities = strategy.prepareForBatch(batchEntities, entity);
- }
- if(log.isDebugEnabled()) log.debug("Add batch values " + ArrayUtils.toString(values));
- entity.addBatch(values, expectedResult);
- }
-
- private BatchEntity findEntity(BatchInfo info)
- {
- for(int i = 0; i < batchEntities.size(); i++)
- {
- BatchEntity batchEntity = (BatchEntity) batchEntities.get(i);
- if(batchEntity.getInfo().equals(info))
- {
- return batchEntity;
- }
- }
- return null;
- }
-
- /** @see BatchManager#executeBatch(BatchEntity) */
- public void executeBatch(BatchEntity entity)
- {
- if(log.isDebugEnabled()) log.debug("Execute BatchEntity performing "
- + entity.batchSize() + " batch entries. BatchEntity=" + entity);
- for(int i = 0; i < batchListener.length; i++)
+ if(log.isDebugEnabled()) log.debug("Execute Batcher performing "
+ + batcher.batchSize() + " batch entries. Batcher=" + batcher);
+ for(int i = 0; i < batchListener.size(); i++)
{
try
{
- batchListener[i].beforeBatchExecution(entity);
+ ((BatchListener) batchListener.get(i)).beforeBatchExecution(batcher);
}
catch(Exception e)
{
- log.error("BatchListener cause exception", e);
- throw new BatchException(
- "Error while perform batch listener before batch execution: " + batchListener[i]);
+ throw new BatchException("Error while perform batch listener before batch execution: "
+ + batchListener.get(i), e);
}
}
@@ -200,32 +156,31 @@
{
try
{
- result = entity.executeBatch();
+ result = batcher.executeBatch(broker.serviceStatementManager(), broker.serviceJdbcAccess());
Platform platform = broker.getConfiguration().getJdbcConnectionDescriptor().getPlatform();
- validator.validateResult(platform, entity.getInfo(), entity.getExpectedResults(), result);
+ validator.validateResult(platform, batcher, result);
}
finally
{
- entity.cleanup();
+ batcher.cleanup();
}
}
catch(SQLException e)
{
- BatchInfo info = entity.getInfo();
- throw ExceptionHelper.generateException(e, info.getSql(), info.getCld(), null, null, log);
+ throw ExceptionHelper.generateException(e, batcher.getSql(), batcher.getClassDescriptor(), null, null, log);
}
- for(int i = 0; i < batchListener.length; i++)
+ for(int i = 0; i < batchListener.size(); i++)
{
try
{
- batchListener[i].afterBatchExecution(entity);
+ ((BatchListener) batchListener.get(i)).afterBatchExecution(batcher);
}
catch(Exception e)
{
log.error("BatchListener cause exception", e);
throw new BatchException(
- "Error while perform batch listener after batch execution: " + batchListener[i]);
+ "Error while perform batch listener after batch execution: " + batchListener.get(i));
}
}
batchLimitCounter -= result.length;
@@ -236,24 +191,24 @@
{
if(batchEntities.size() == 0) return;
- if(log.isDebugEnabled()) log.debug("Excecute batch call on " + batchEntities.size() + " BatchEntity instances");
+ if(log.isDebugEnabled()) log.debug("Excecute batch call on " + batchEntities.size() + " Batcher instances");
try
{
Iterator it = batchEntities.iterator();
- BatchEntity entity;
+ Batcher batcher;
while(it.hasNext())
{
- entity = (BatchEntity) it.next();
- executeBatch(entity);
+ batcher = (Batcher) it.next();
+ executeBatch(batcher);
}
}
finally
{
- cancelBatch();
+ cleanupAndPrepare();
}
}
- public boolean checkBatchLimit()
+ public boolean batchLimitReached()
{
return batchLimitCounter > batchLimit;
}
@@ -261,49 +216,39 @@
/** @see BatchManager#cancelBatch */
public void cancelBatch()
{
+ cleanupAndPrepare();
+ }
+
+ /**
+ * Cleanup and prepare for reuse.
+ */
+ private void cleanupAndPrepare()
+ {
batchEntities.clear();
resetBatchCount();
}
public void addBatchListener(BatchListener listener)
{
- BatchListener[] newListeners = new BatchListener[batchListener.length + 1];
- System.arraycopy(batchListener, 0, newListeners, 0, batchListener.length);
- newListeners[newListeners.length - 1] = listener;
- batchListener = newListeners;
+ if(!batchListener.contains(listener))
+ {
+ batchListener.add(listener);
+ }
+ else
+ {
+ log.info("BatchListener add: Already added listener found, will ignore multiple listener add");
+ }
}
public void removeBatchListener(BatchListener listener)
{
- if(batchListener.length == 0) return;
-
- BatchListener[] newListeners = new BatchListener[batchListener.length - 1];
- int pos = 0;
- boolean match = false;
- for(int i = 0; i < batchListener.length; i++)
- {
- if(batchListener[i] != listener)
- {
- if(pos == batchListener.length)
- {
- // no listener match, break and don't change listener array
- log.info("Given BatchListener does not match, can't remove listener: " + listener);
- break;
- }
- newListeners[pos++] = batchListener[i];
- }
- else
- {
- match = true;
- }
- }
- if(match) batchListener = newListeners;
+ batchListener.remove(listener);
}
public void reset()
{
cancelBatch();
- batchListener = NULL_LISTENER;
+ batchListener.clear();
}
public void setBatchLimit(int limit)
@@ -348,7 +293,7 @@
}
/**
- * Was called by {@link BatchEntity} when a new set of values
+ * Was called by {@link Batcher} when a new set of values
* are added to batch.
*/
void increaseBatchCount()
@@ -359,5 +304,43 @@
private void resetBatchCount()
{
batchLimitCounter = 0;
+ }
+
+ public void add(Batcher batcher, ValueContainer[] values, int expectedResult) throws SQLException
+ {
+ if(batchLimitReached())
+ {
+ if(log.isEnabledFor(Logger.INFO))
+ {
+ log.info("Batch limit reached, execute batch before add new batch entry");
+ }
+ executeBatch();
+ }
+
+ Batcher entity = checkForExistingBatcher(batcher);
+ if(entity == null)
+ {
+ entity = batcher;
+ if(log.isDebugEnabled()) log.debug("Add new Batcher: " + batcher);
+ // lookup batch strategy and ask for updated (reordered, reduced, ...)
+ // list of batch entities
+ batchEntities = strategy.prepareForBatch(batchEntities, batcher);
+ }
+ if(log.isDebugEnabled()) log.debug("Add batch value row on batcher " + entity + ", values are "+ ArrayUtils.toString(values));
+ entity.add(values, expectedResult);
+ increaseBatchCount();
+ }
+
+ private Batcher checkForExistingBatcher(Batcher newBatcher)
+ {
+ for(int i = 0; i < batchEntities.size(); i++)
+ {
+ Batcher batcher = (Batcher) batchEntities.get(i);
+ if(batcher.equals(newBatcher))
+ {
+ return batcher;
+ }
+ }
+ return null;
}
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategy.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategy.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategy.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategy.java Fri Jan 12 10:19:39 2007
@@ -22,25 +22,24 @@
import org.apache.ojb.broker.OptimisticLockException;
/**
- * This class is reponsible for order of {@link BatchEntity} instances.
+ * This class is reponsible for order of {@link Batcher} instances.
*
- * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
* @version $Id$
*/
public interface BatchStrategy
{
/**
- * Prepare the current enqueued {@link BatchEntity} objects for add of
+ * Prepare the current enqueued {@link Batcher} objects for add of
* the new entity - in general the strategy checks for conflicts with
- * the new entity and execute the batch
+ * the new entity and execute the batch.
*
- * @param entities A collection of already enqueued {@link BatchEntity} objects.
- * @param newEntity The new {@link BatchEntity} to add to batch queue.
+ * @param entities A collection of already enqueued {@link Batcher} objects.
+ * @param newEntity The new {@link Batcher} to add to batch queue.
* @return The new batch entity list <strong>including</strong> the new entity
- * (the order or/and the number of {@link BatchEntity} can be different from the orginal).
+ * (the order or/and the number of {@link Batcher} can be different from the orginal).
* @throws OptimisticLockException
*/
- List prepareForBatch(List entities, BatchEntity newEntity) throws OptimisticLockException;
+ List prepareForBatch(List entities, Batcher newEntity) throws OptimisticLockException;
/**
* Close this batch strategy.
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategyBase.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategyBase.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategyBase.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategyBase.java Fri Jan 12 10:19:39 2007
@@ -26,7 +26,6 @@
* {@link org.apache.ojb.broker.accesslayer.batch.BatchStrategyBase.TranspositionBan} interface to
* control the order of batch entries.
*
- * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
* @version $Id$
*/
public abstract class BatchStrategyBase implements BatchStrategy
@@ -49,7 +48,7 @@
*/
public abstract TranspositionBan[] getTranspositionBans();
- public List prepareForBatch(List entities, BatchEntity newEntity) throws OptimisticLockException
+ public List prepareForBatch(List entities, Batcher newEntity) throws OptimisticLockException
{
/*
only new batch entity objects need to be checked.
@@ -73,27 +72,31 @@
CHECK_BANS_LOOP:
for(int i = entities.size() - 1; i >= 0; i--)
{
- BatchEntity next = (BatchEntity) entities.get(i);
+ Batcher next = (Batcher) entities.get(i);
for(int j = 0; j < bans.length; j++)
{
- if(bans[j].isBanned(newEntity.getInfo(), next.getInfo()))
+ if(bans[j].isBanned(newEntity, next))
{
toExecute = i + 1;
break CHECK_BANS_LOOP;
}
}
}
+ //System.out.println("*Batcher_before: " + entities.size());
if(toExecute > 0)
{
for(Iterator it = entities.iterator();
(toExecute > 0) && it.hasNext(); toExecute--)
{
- BatchEntity next = (BatchEntity) it.next();
+ Batcher next = (Batcher) it.next();
batchManager.executeBatch(next);
it.remove();
+ //System.out.println("*remove: " + next);
}
}
+ //System.out.println("*add: " + newEntity);
entities.add(newEntity);
+ //System.out.println("*Batcher_after: " + entities.size());
return entities;
}
@@ -105,10 +108,10 @@
/**
* Is transposition of batch entries of the given type banned?
*
- * @param infoNew The {@link BatchInfo} of the new or first batch entry.
- * @param infoOld The {@link BatchInfo} of the already buffered batch entry.
+ * @param batcher The {@link Batcher} of the new or first batch entry.
+ * @param batcherOther The {@link Batcher} of the already buffered batch entry.
* @return <em>True</em> if transposition is banned.
*/
- public boolean isBanned(BatchInfo infoNew, BatchInfo infoOld);
+ public boolean isBanned(Batcher batcher, Batcher batcherOther);
}
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategyDefaultImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategyDefaultImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategyDefaultImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/BatchStrategyDefaultImpl.java Fri Jan 12 10:19:39 2007
@@ -27,16 +27,15 @@
* follows from the known relations between tables,
* reflected in repository.xml.
*
- * @author <a href="mailto:olegnitz@apache.org">Oleg Nitz</a>
* @version $Id$
*/
public class BatchStrategyDefaultImpl extends BatchStrategyBase
{
private TranspositionBan[] bans = new TranspositionBan[]{
- new InsertTranspositionBan(),
- new DeleteTranspositionBan(),
- new TheSameTableTranspositionBan(),
+ new InsertTranspositionBan(),
+ new DeleteTranspositionBan(),
+ new TheSameTableTranspositionBan(),
};
public BatchStrategyDefaultImpl(BatchManager batchManager)
@@ -55,18 +54,17 @@
/**
* Does cld1 have reference to cld2?
*/
- private boolean hasReferenceTo(BatchInfo infoNew, BatchInfo infoOld)
+ private boolean hasReferenceTo(Batcher infoNew, Batcher infoOld)
{
- if(infoNew.getCld() != null && infoOld.getCld() != null)
+ if(infoNew.getClassDescriptor() != null && infoOld.getClassDescriptor() != null)
{
- List ordList = infoNew.getCld().getObjectReferenceDescriptors();
+ List ordList = infoNew.getClassDescriptor().getObjectReferenceDescriptors();
if(!ordList.isEmpty())
{
- Class class2 = infoOld.getCld().getClassOfObject();
+ Class class2 = infoOld.getClassDescriptor().getClassOfObject();
for(Iterator it = ordList.iterator(); it.hasNext();)
{
- ObjectReferenceDescriptor ord =
- (ObjectReferenceDescriptor) it.next();
+ ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) it.next();
if(ord.getItemClass().isAssignableFrom(class2))
{
return true;
@@ -80,20 +78,18 @@
/**
* Does cld1 have collection of cld2?
*/
- private boolean hasCollection1ToNOf(BatchInfo infoNew, BatchInfo infoOld)
+ private boolean hasCollection1ToNOf(Batcher infoNew, Batcher infoOld)
{
- if(infoNew.getCld() != null && infoOld.getCld() != null)
+ if(infoNew.getClassDescriptor() != null && infoOld.getClassDescriptor() != null)
{
- List codList = infoNew.getCld().getCollectionDescriptors();
+ List codList = infoNew.getClassDescriptor().getCollectionDescriptors();
if(!codList.isEmpty())
{
- Class class2 = infoOld.getCld().getClassOfObject();
+ Class class2 = infoOld.getClassDescriptor().getClassOfObject();
for(Iterator it2 = codList.iterator(); it2.hasNext();)
{
- CollectionDescriptor cod =
- (CollectionDescriptor) it2.next();
- if(!cod.isMtoNRelation()
- && cod.getItemClass().isAssignableFrom(class2))
+ CollectionDescriptor cod = (CollectionDescriptor) it2.next();
+ if(!cod.isMtoNRelation() && cod.getItemClass().isAssignableFrom(class2))
{
return true;
}
@@ -103,6 +99,33 @@
return false;
}
+ /**
+ * Is the first argument a indirection table entry and the other batch entry has
+ * a m:n reference to this indirection table?
+ */
+ private boolean isIndirectionTableOf(Batcher potentialIndirectionTable, Batcher potentialReference)
+ {
+ boolean result = false;
+ if(potentialIndirectionTable.isIndirectionTable() && potentialReference.getClassDescriptor() != null)
+ {
+ //System.out.println("# ind: " + potentialIndirectionTable);
+ //System.out.println("# ref: " + potentialReference);
+ List descriptors = potentialReference.getClassDescriptor().getCollectionDescriptors();
+ for(int i = 0; i < descriptors.size(); i++)
+ {
+ CollectionDescriptor colDes = (CollectionDescriptor) descriptors.get(i);
+ if(colDes.isMtoNRelation() && colDes.getIndirectionTableDescriptor().getTableName()
+ .equals(potentialIndirectionTable.getTableName()))
+ {
+ result = true;
+ break;
+ }
+ }
+ //System.out.println("result: " + result);
+ }
+ return result;
+ }
+
//-------------------- Inner classes -----------------------
/**
@@ -112,19 +135,12 @@
*/
public class InsertTranspositionBan implements TranspositionBan
{
- public boolean isBanned(BatchInfo infoNew,
- BatchInfo infoOld)
+ public boolean isBanned(Batcher infoNew, Batcher infoOld)
{
- return ((infoNew.getType() == BatchInfo.TYPE_OBJECT_INSERT)
-
- && ((infoOld.getType() == BatchInfo.TYPE_OBJECT_INSERT)
- || (infoOld.getType() == BatchInfo.TYPE_OBJECT_UPDATE))
-
- && (hasReferenceTo(infoOld, infoNew)
- || hasCollection1ToNOf(infoNew, infoOld))
-
- );
- // TODO M:N indirection table
+ return infoNew.isInsert() &&
+ (((infoOld.isInsert() || infoOld.isUpdate())
+ && (hasReferenceTo(infoOld, infoNew) || hasCollection1ToNOf(infoNew, infoOld))
+ ) || infoOld.isInsert() && isIndirectionTableOf(infoOld, infoNew));
}
}
@@ -136,19 +152,12 @@
*/
public class DeleteTranspositionBan implements TranspositionBan
{
- public boolean isBanned(BatchInfo infoNew,
- BatchInfo infoOld)
+ public boolean isBanned(Batcher infoNew, Batcher infoOld)
{
- return (((infoNew.getType() == BatchInfo.TYPE_OBJECT_DELETE)
- || (infoNew.getType() == BatchInfo.TYPE_OBJECT_UPDATE))
-
- && (infoOld.getType() == BatchInfo.TYPE_OBJECT_DELETE)
-
- && (hasReferenceTo(infoNew, infoOld)
- || hasCollection1ToNOf(infoOld, infoNew))
-
- );
- // TODO M:N indirection table
+ return (infoNew.isDelete() || infoNew.isUpdate()) &&
+ (((infoOld.isDelete()) &&
+ (hasReferenceTo(infoNew, infoOld) || hasCollection1ToNOf(infoOld, infoNew))
+ ) || infoOld.isDelete() && isIndirectionTableOf(infoNew, infoOld));
}
}
@@ -159,28 +168,14 @@
*/
public class TheSameTableTranspositionBan implements TranspositionBan
{
- public boolean isBanned(BatchInfo infoNew,
- BatchInfo infoOld)
+ public boolean isBanned(Batcher infoNew,
+ Batcher infoOld)
{
- // TODO M:N indirection table
- return (
- infoNew.getCld() != null
- && infoOld.getCld() != null
- && infoNew.getCld().getFullTableName().equals(infoOld.getCld().getFullTableName())
- &&
+ return infoNew.getTableName().equals(infoOld.getTableName()) &&
(
- ((infoNew.getType() == BatchInfo.TYPE_OBJECT_INSERT)
- && (infoOld.getType() == BatchInfo.TYPE_OBJECT_UPDATE))
-
- || ((infoNew.getType() == BatchInfo.TYPE_OBJECT_UPDATE)
- && (infoOld.getType() == BatchInfo.TYPE_OBJECT_DELETE))
-
- || ((infoNew.getType() == BatchInfo.TYPE_OBJECT_INSERT)
- && (infoOld.getType() == BatchInfo.TYPE_OBJECT_DELETE))
-
- || ((infoNew.getType() == BatchInfo.TYPE_OBJECT_DELETE)
- && (infoOld.getType() == BatchInfo.TYPE_OBJECT_INSERT))
- )
+ (infoNew.isInsert() && (infoOld.isUpdate() || infoOld.isDelete()))
+ || (infoNew.isUpdate() && infoOld.isDelete())
+ || (infoNew.isDelete() && infoOld.isInsert())
);
}
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/ReturnValueValidator.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/ReturnValueValidator.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/ReturnValueValidator.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/ReturnValueValidator.java Fri Jan 12 10:19:39 2007
@@ -15,7 +15,6 @@
* limitations under the License.
*/
-import java.lang.Object;
import java.sql.SQLException;
import org.apache.ojb.broker.OptimisticLockException;
@@ -34,11 +33,13 @@
* results (number of affected rows) with the <em>real</em> returned result array.
*
* @param platform The used platform.
- * @param info The {@link BatchInfo} batch metadata.
- * @param expectedResults The expected return value array.
+ * @param batcher The {@link Batcher} instance.
* @param result The real return value array.
- * @throws java.sql.SQLException If the return values are illegal or signal batch entries execution failures.
+ * @throws java.sql.SQLException If the return values are illegal or signal
+ * batch entries execution failures.
* @throws org.apache.ojb.broker.OptimisticLockException If an optimistic lock issue occur.
*/
- void validateResult(Platform platform, BatchInfo info, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException;
+ void validateResult(Platform platform, Batcher batcher, int[] result)
+ throws SQLException, OptimisticLockException;
+
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/ReturnValueValidatorImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/ReturnValueValidatorImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/ReturnValueValidatorImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/batch/ReturnValueValidatorImpl.java Fri Jan 12 10:19:39 2007
@@ -36,18 +36,7 @@
{
}
- /**
- * Validates the batch statement execution result value array by comparing the expected
- * results (number of affected rows) with the <em>real</em> returned result array.
- *
- * @param platform The used platform.
- * @param info The {@link org.apache.ojb.broker.accesslayer.batch.BatchInfo} batch metadata.
- * @param expectedResults The expected return value array.
- * @param result The real return value array.
- * @throws SQLException If the return values are illegal or signal batch entries execution failures.
- * @throws OptimisticLockException If an optimistic lock issue occur.
- */
- public void validateResult(Platform platform, BatchInfo info, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
+ public void validateResult(Platform platform, Batcher batcher, int[] result) throws SQLException, OptimisticLockException
{
/*
a batch execution failed when
@@ -56,27 +45,28 @@
- it signal a failure while statement execution
- optimistic lock issue
*/
+ int[] expectedResults = batcher.getExpectedResults();
if(result != null && result.length == expectedResults.length)
{
- switch(info.getType())
+ switch(batcher.getType())
{
- case BatchInfo.TYPE_OBJECT_UPDATE:
- validateUpdate(info, expectedResults, result);
+ case Batcher.TYPE_UPDATE:
+ validateUpdate(batcher, expectedResults, result);
break;
- case BatchInfo.TYPE_OBJECT_INSERT:
- validateInsert(info, expectedResults, result);
+ case Batcher.TYPE_INSERT:
+ validateInsert(batcher, expectedResults, result);
break;
- case BatchInfo.TYPE_OBJECT_DELETE:
- validateDelete(info, expectedResults, result);
+ case Batcher.TYPE_DELETE:
+ validateDelete(batcher, expectedResults, result);
break;
- case BatchInfo.TYPE_INDIRECTION_TABLE_DELETE:
- validateIndirectionTableDelete(info, expectedResults, result);
+ case Batcher.TYPE_INDIRECTION_TABLE_DELETE:
+ validateIndirectionTableDelete(batcher, expectedResults, result);
break;
- case BatchInfo.TYPE_INDIRECTION_TABLE_INSERT:
- validateIndirectionTableInsert(info, expectedResults, result);
+ case Batcher.TYPE_INDIRECTION_TABLE_INSERT:
+ validateIndirectionTableInsert(batcher, expectedResults, result);
break;
default:
- validateUnkownType(info, expectedResults, result);
+ validateUnkownType(batcher, expectedResults, result);
}
}
else
@@ -91,13 +81,13 @@
/**
* FOR INTERNAL USE ONLY! Validates UPDATE operation batch statement execution results.
*
- * @param info The {@link BatchInfo} batch metadata.
+ * @param batcher The {@link Batcher} batch metadata.
* @param expectedResults The expected return value array.
* @param result The real return value array.
* @throws SQLException If the return values are illegal or signal batch entries execution failures.
* @throws OptimisticLockException If an optimistic lock issue occur.
*/
- protected void validateUpdate(BatchInfo info, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
+ protected void validateUpdate(Batcher batcher, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
{
for(int i = 0; i < result.length; i++)
{
@@ -106,29 +96,29 @@
{
if(resultValue == PreparedStatement.EXECUTE_FAILED)
{
- throw throwExecuteFailed(info, expectedResults, result, i);
+ throw throwExecuteFailed(batcher, expectedResults, result, i);
}
- else if(info.useOptimisticLocking())
+ else if(batcher.useOptimisticLocking())
{
// on insert of objects with enabled opt. locking we allow unverified
// return values, otherwise we throw an exception
if(resultValue == Statement.SUCCESS_NO_INFO)
{
- if(info.getType() != BatchInfo.TYPE_OBJECT_INSERT)
+ if(batcher.getType() != Batcher.TYPE_INSERT)
{
- throw throwJdbcNotSupported(info, expectedResults, result, i);
+ throw throwJdbcNotSupported(batcher, expectedResults, result, i);
}
}
else
{
- throw throwOptimisticLock(info, expectedResults, result, i);
+ throw throwOptimisticLock(batcher, expectedResults, result, i);
}
}
else if(!(resultValue == PreparedStatement.SUCCESS_NO_INFO
|| resultValue == PreparedStatement.CLOSE_ALL_RESULTS
|| resultValue == 0))
{
- throw throwUnexpectedValue(info, expectedResults, result, i);
+ throw throwUnexpectedValue(batcher, expectedResults, result, i);
}
}
}
@@ -137,13 +127,13 @@
/**
* FOR INTERNAL USE ONLY! Validates INSERT operation batch statement execution results.
*
- * @param info The {@link BatchInfo} batch metadata.
+ * @param batcher The {@link Batcher} batch metadata.
* @param expectedResults The expected return value array.
* @param result The real return value array.
* @throws SQLException If the return values are illegal or signal batch entries execution failures.
* @throws OptimisticLockException If an optimistic lock issue occur.
*/
- protected void validateInsert(BatchInfo info, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
+ protected void validateInsert(Batcher batcher, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
{
for(int i = 0; i < result.length; i++)
{
@@ -152,11 +142,11 @@
{
if(resultValue == PreparedStatement.EXECUTE_FAILED)
{
- throw throwExecuteFailed(info, expectedResults, result, i);
+ throw throwExecuteFailed(batcher, expectedResults, result, i);
}
else if(resultValue != PreparedStatement.SUCCESS_NO_INFO)
{
- throw throwUnexpectedValue(info, expectedResults, result, i);
+ throw throwUnexpectedValue(batcher, expectedResults, result, i);
}
}
}
@@ -165,13 +155,13 @@
/**
* FOR INTERNAL USE ONLY! Validates DELETE operation batch statement execution results.
*
- * @param info The {@link BatchInfo} batch metadata.
+ * @param batcher The {@link Batcher} batch metadata.
* @param expectedResults The expected return value array.
* @param result The real return value array.
* @throws SQLException If the return values are illegal or signal batch entries execution failures.
* @throws OptimisticLockException If an optimistic lock issue occur.
*/
- protected void validateDelete(BatchInfo info, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
+ protected void validateDelete(Batcher batcher, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
{
for(int i = 0; i < result.length; i++)
{
@@ -180,28 +170,28 @@
{
if(resultValue == PreparedStatement.EXECUTE_FAILED)
{
- throw throwExecuteFailed(info, expectedResults, result, i);
+ throw throwExecuteFailed(batcher, expectedResults, result, i);
}
- else if(info.useOptimisticLocking())
+ else if(batcher.useOptimisticLocking())
{
// on insert of objects with enabled opt. locking we allow unverified
// return values, otherwise we throw an exception
if(resultValue == Statement.SUCCESS_NO_INFO)
{
- if(info.getType() != BatchInfo.TYPE_OBJECT_INSERT)
+ if(batcher.getType() != Batcher.TYPE_INSERT)
{
- throw throwJdbcNotSupported(info, expectedResults, result, i);
+ throw throwJdbcNotSupported(batcher, expectedResults, result, i);
}
}
else
{
- throw throwOptimisticLock(info, expectedResults, result, i);
+ throw throwOptimisticLock(batcher, expectedResults, result, i);
}
}
else if(!(resultValue == PreparedStatement.SUCCESS_NO_INFO
|| resultValue == 0))
{
- throw throwUnexpectedValue(info, expectedResults, result, i);
+ throw throwUnexpectedValue(batcher, expectedResults, result, i);
}
}
}
@@ -210,13 +200,13 @@
/**
* FOR INTERNAL USE ONLY! Validates m:n-INDIRECTIONTABLE-INSERT operation batch statement execution results.
*
- * @param info The {@link BatchInfo} batch metadata.
+ * @param batcher The {@link Batcher} batch metadata.
* @param expectedResults The expected return value array.
* @param result The real return value array.
* @throws SQLException If the return values are illegal or signal batch entries execution failures.
* @throws OptimisticLockException If an optimistic lock issue occur.
*/
- protected void validateIndirectionTableInsert(BatchInfo info, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
+ protected void validateIndirectionTableInsert(Batcher batcher, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
{
for(int i = 0; i < result.length; i++)
{
@@ -227,11 +217,11 @@
{
if(resultValue == PreparedStatement.EXECUTE_FAILED)
{
- throw throwExecuteFailed(info, expectedResults, result, i);
+ throw throwExecuteFailed(batcher, expectedResults, result, i);
}
else if(resultValue != PreparedStatement.SUCCESS_NO_INFO)
{
- throw throwUnexpectedValue(info, expectedResults, result, i);
+ throw throwUnexpectedValue(batcher, expectedResults, result, i);
}
}
}
@@ -240,13 +230,13 @@
/**
* FOR INTERNAL USE ONLY! Validates m:n-INDIRECTIONTABLE-DELETE operation batch statement execution results.
*
- * @param info The {@link BatchInfo} batch metadata.
+ * @param batcher The {@link Batcher} batch metadata.
* @param expectedResults The expected return value array.
* @param result The real return value array.
* @throws SQLException If the return values are illegal or signal batch entries execution failures.
* @throws OptimisticLockException If an optimistic lock issue occur.
*/
- protected void validateIndirectionTableDelete(BatchInfo info, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
+ protected void validateIndirectionTableDelete(Batcher batcher, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
{
for(int i = 0; i < result.length; i++)
{
@@ -256,13 +246,13 @@
{
if(resultValue == PreparedStatement.EXECUTE_FAILED)
{
- throw throwExecuteFailed(info, expectedResults, result, i);
+ throw throwExecuteFailed(batcher, expectedResults, result, i);
}
else if(!(resultValue == PreparedStatement.SUCCESS_NO_INFO
|| resultValue == PreparedStatement.CLOSE_ALL_RESULTS
|| resultValue == 0))
{
- throw throwUnexpectedValue(info, expectedResults, result, i);
+ throw throwUnexpectedValue(batcher, expectedResults, result, i);
}
}
}
@@ -271,30 +261,30 @@
/**
* FOR INTERNAL USE ONLY! Validates UNKOWN TYPES of batch statement execution results.
*
- * @param info The {@link BatchInfo} batch metadata.
+ * @param batcher The {@link Batcher} batch metadata.
* @param expectedResults The expected return value array.
* @param result The real return value array.
* @throws SQLException If the return values are illegal or signal batch entries execution failures.
* @throws OptimisticLockException If an optimistic lock issue occur.
*/
- protected void validateUnkownType(BatchInfo info, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
+ protected void validateUnkownType(Batcher batcher, int[] expectedResults, int[] result) throws SQLException, OptimisticLockException
{
for(int i = 0; i < result.length; i++)
{
int resultValue = result[i];
if(resultValue == Statement.EXECUTE_FAILED)
{
- throwExecuteFailed(info, expectedResults, result, i);
+ throwExecuteFailed(batcher, expectedResults, result, i);
}
// arminw: when OJB perform an unkown batch sql-query we don't know the return value 0,1,2....
// if(expectedResults[i] > resultValue)
// {
-// throw throwUnexpectedValue(info, expectedResults, result, i);
+// throw throwUnexpectedValue(batcher, expectedResults, result, i);
// }
}
}
- protected SQLException throwExecuteFailed(BatchInfo info, int[] expectedResults, int[] result, int index)
+ protected SQLException throwExecuteFailed(Batcher batcher, int[] expectedResults, int[] result, int index)
{
String eol = SystemUtils.LINE_SEPARATOR;
return new SQLException(
@@ -304,7 +294,7 @@
"', but found " + ReflectionHelper.reflectNameFor(Statement.class, result[index]));
}
- protected SQLException throwJdbcNotSupported(BatchInfo info, int[] expectedResults, int[] result, int index)
+ protected SQLException throwJdbcNotSupported(Batcher batcher, int[] expectedResults, int[] result, int index)
{
String eol = SystemUtils.LINE_SEPARATOR;
return new SQLException("JDBC driver does support batch statements but does not"
@@ -316,10 +306,10 @@
+ eol + " Please use a more sophisticated JDBC driver or a BatchManager implementation"
+ eol + " which provide a specific property to exclude objects using optimistic locking"
+ eol + " from being put to batch (OJB's default impl. class supports such a property)."
- + eol + " Used BatchInfo instance: " + eol + info);
+ + eol + " Used Batcher instance: " + eol + batcher);
}
- protected SQLException throwUnexpectedValue(BatchInfo info, int[] expectedResults, int[] result, int index)
+ protected SQLException throwUnexpectedValue(Batcher batcher, int[] expectedResults, int[] result, int index)
{
return new SQLException("Execute batch returned an unexpected statement return" +
" value (row count result)." +
@@ -328,12 +318,12 @@
ReflectionHelper.reflectNameFor(Statement.class, result[index]));
}
- protected OptimisticLockException throwOptimisticLock(BatchInfo info, int[] expectedResults, int[] result, int index)
+ protected OptimisticLockException throwOptimisticLock(Batcher batcher, int[] expectedResults, int[] result, int index)
{
String eol = SystemUtils.LINE_SEPARATOR;
return new OptimisticLockException("Detect optimistic locking conflict while statement" +
" execution for batch command number '" + (index + 1) + "' of '" + result.length + "' commands" +
". Expected statement return value (row count) was '" + expectedResults[index] +
- "', but found '" + result[index] + "'." + eol + " Used BatchInfo instance: " + eol + info);
+ "', but found '" + result[index] + "'." + eol + " Used Batcher instance: " + eol + batcher);
}
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SelectStatement.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SelectStatement.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SelectStatement.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SelectStatement.java Fri Jan 12 10:19:39 2007
@@ -19,9 +19,8 @@
import org.apache.ojb.broker.query.Query;
/**
- * This class
+ * Encapsulates methodes of select statements.
*
- * @author <a href="mailto:arminw@apache.org">Armin Waibel</a>
* @version $Id$
*/
public interface SelectStatement extends SqlStatement
@@ -51,4 +50,9 @@
* case this method returns <em>true</em>.
*/
public boolean isUseOjbClassColumn();
+
+ /**
+ * Returns <em>true</em> if the statement is a stored procedure.
+ */
+ public boolean isStoredProcedure();
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlProcedureFKStatement.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlProcedureFKStatement.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlProcedureFKStatement.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlProcedureFKStatement.java Fri Jan 12 10:19:39 2007
@@ -33,9 +33,6 @@
* Model a call to a stored procedure based on ProcedureDescriptors
*
* @see org.apache.ojb.broker.metadata.ProcedureDescriptor
- * @author <a href="mailto:rburt3@mchsi.com">Randall Burt</a>
- * @author <a href="mailto:rgallagh@bellsouth.net">Ron Gallagher</a>
- * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
* @version $Id$
*/
public class SqlProcedureFKStatement implements SelectStatement
@@ -140,5 +137,10 @@
public boolean isUseOjbClassColumn()
{
return false;
+ }
+
+ public boolean isStoredProcedure()
+ {
+ return true;
}
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlProcedureStatement.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlProcedureStatement.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlProcedureStatement.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlProcedureStatement.java Fri Jan 12 10:19:39 2007
@@ -25,8 +25,6 @@
* Model a call to a stored procedure based on ProcedureDescriptors
*
* @see org.apache.ojb.broker.metadata.ProcedureDescriptor
- * @author <a href="mailto:rburt3@mchsi.com">Randall Burt</a>
- * @author <a href="mailto:rgallagh@bellsouth.net">Ron Gallagher</a>
* @version $Id$
*/
@@ -107,5 +105,10 @@
public boolean isUseOjbClassColumn()
{
return false;
+ }
+
+ public boolean isStoredProcedure()
+ {
+ return true;
}
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java Fri Jan 12 10:19:39 2007
@@ -340,30 +340,9 @@
orderByFields = query.getOrderBy();
columnList = ensureColumns(orderByFields, columnList, stmt);
-/*
-arminw:
-TODO: this feature doesn't work, so remove this in future
-*/
- /**
- * treeder: going to map superclass tables here,
- * not sure about the columns, just using all columns for now
- */
- ClassDescriptor cld = getBaseClassDescriptor();
- ClassDescriptor cldSuper = null;
- if (cld.getSuperClass() != null)
- {
- // then we have a super class so join tables
- cldSuper = cld.getRepository().getDescriptorFor(cld.getSuperClass());
- appendSuperClassColumns(cldSuper, stmt);
- }
stmt.append(" FROM ");
appendTableWithJoins(getRootAlias(), where, stmt);
-
- if (cld.getSuperClass() != null)
- {
- appendSuperClassJoin(cld, cldSuper, stmt, where);
- }
appendWhereClause(where, whereCrit, stmt);
appendGroupByClause(groupByFields, stmt);
@@ -377,52 +356,16 @@
((ReportQueryByCriteria) query).setAttributeFieldDescriptors(getAttributesToFieldDescriptors());
}
- return stmt.toString();
- }
-
-/*
-arminw:
-TODO: this feature doesn't work, so remove this in future
-*/
- private void appendSuperClassJoin(ClassDescriptor cld, ClassDescriptor cldSuper, StringBuffer stmt, StringBuffer where)
- {
- stmt.append(",");
- appendTable(cldSuper, stmt);
-
- if (where != null)
+ if(query.isSelectForUpdate())
{
- if (where.length() > 0)
- {
- where.append(" AND ");
- }
-
- // get reference field in super class
- // TODO: do not use the superclassfield anymore, just assume that the id is the same in both tables - @see PBroker.storeToDb
- int superFieldRef = cld.getSuperClassFieldRef();
- FieldDescriptor refField = cld.getFieldDescriptorByIndex(superFieldRef);
-
- appendTable(cldSuper, where);
- where.append(".");
- appendField(cldSuper.getAutoIncrementFields()[0], where);
- where.append(" = ");
- appendTable(cld, where);
- where.append(".");
- appendField(refField, where);
+ stmt.append(getPlatform().getSelectForUpdateClause());
}
- }
-
- private void appendSuperClassColumns(ClassDescriptor cldSuper, StringBuffer buf)
- {
- FieldDescriptor[] fields = cldSuper.getFieldDescriptions();
- for (int i = 0; i < fields.length; i++)
+ if(query.getQueryAffix() != null)
{
- FieldDescriptor field = fields[i];
- if (i > 0)
- {
- buf.append(",");
- }
- appendColumn(cldSuper.getFullTableName(), field.getColumnName(), buf);
+ stmt.append(" ").append(query.getQueryAffix());
}
+
+ return stmt.toString();
}
/**
@@ -475,5 +418,10 @@
protected void setUseOjbClassColumn(boolean useOjbClassColumn)
{
this.useOjbClassColumn = useOjbClassColumn;
+ }
+
+ public boolean isStoredProcedure()
+ {
+ return false;
}
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/AbstractObjectCache.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/AbstractObjectCache.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/AbstractObjectCache.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/AbstractObjectCache.java Fri Jan 12 10:19:39 2007
@@ -1,11 +1,11 @@
package org.apache.ojb.broker.cache;
import java.util.Iterator;
-import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
-import org.apache.commons.collections.map.ReferenceIdentityMap;
-import org.apache.commons.collections.map.ReferenceMap;
import org.apache.ojb.broker.Identity;
+import org.apache.ojb.broker.util.WeakIdentityList;
/* Copyright 2002-2004 The Apache Software Foundation
*
@@ -23,33 +23,41 @@
*/
/**
- * Base class to provide the extended functionality of {@link ObjectCacheExt}
- * to all {@link ObjectCache} implementations extending this class.
+ * Base class to provide the common functionality of {@link ObjectCache}.
*
* @version $Id$
*/
-abstract public class AbstractObjectCache implements ObjectCacheExt
+abstract public class AbstractObjectCache implements ObjectCache
{
- private final Object dummy = new Object();
- private Map listeners;
+ private final Object sync = new Object();
+ private List listeners;
- private Map createListenerMap()
+ /**
+ * Implement this method to cache objects.
+ *
+ * @param oid The {@link org.apache.ojb.broker.Identity} of the object.
+ * @param obj The object to cache.
+ */
+ abstract public void doCache(Identity oid, Object obj);
+
+ /**
+ * Internally called for each object cached by this cache implementation.
+ *
+ * @param oid The {@link org.apache.ojb.broker.Identity} of the cached object.
+ */
+ void performInvalidationAction(Identity oid)
{
- return new ReferenceIdentityMap(ReferenceMap.WEAK, ReferenceMap.HARD, true);
- }
-
- protected void performInvalidationAction(Identity oid)
- {
- if(listeners == null) return;
-
- synchronized(dummy)
+ if(listeners != null)
{
- Iterator it = listeners.keySet().iterator();
- InvalidationListener target;
- while(it.hasNext())
+ synchronized(sync)
{
- target = (InvalidationListener) it.next();
- if(target != null) target.invalidateObject(oid);
+ Iterator it = listeners.iterator();
+ InvalidationListener target;
+ while(it.hasNext())
+ {
+ target = (InvalidationListener) it.next();
+ if(target != null) target.invalidateObject(oid);
+ }
}
}
}
@@ -60,15 +68,13 @@
{
throw new NullPointerException("Added InvalidationListener can't be 'null'");
}
- if(listeners == null)
+ synchronized(sync)
{
- listeners = createListenerMap();
- }
- // dummy value
- Integer id = new Integer(System.identityHashCode(listener));
- synchronized(dummy)
- {
- if(!listeners.containsKey(listener)) listeners.put(listener, id);
+ if(listeners == null)
+ {
+ listeners = new WeakIdentityList();
+ }
+ if(!listeners.contains(listener)) listeners.add(listener);
}
}
@@ -79,7 +85,7 @@
{
throw new NullPointerException("InvalidationListener can't be 'null'");
}
- synchronized(dummy)
+ synchronized(sync)
{
listeners.remove(listener);
if(listeners.size() == 0)
@@ -89,25 +95,50 @@
}
}
+ public List getAllInvalidationListener()
+ {
+ List result = new ArrayList();
+ synchronized(sync)
+ {
+ Iterator it = listeners.iterator();
+ while(it.hasNext())
+ {
+ result.add(it.next());
+ }
+ }
+ return result;
+ }
+
public void invalidateObject(Identity oid)
{
/*
- invalidate object by direct call to the underlying ObjectCacheExt
+ invalidate object by direct call to the underlying cache
instance, never use the #remove(oid) method to invalidate to avoid problems
with caches which add each other as listener.
*/
remove(oid);
}
+ /**
+ * Not allowed to override this method to guaratee call of
+ * invalidation action. Use methode {@link #doCache(org.apache.ojb.broker.Identity, Object)}
+ * to implement cache method.
+ */
+ final public void cache(final Identity oid, final Object obj)
+ {
+ doCache(oid, obj);
+ performInvalidationAction(oid);
+ }
+
public String toString()
{
StringBuffer msg = new StringBuffer();
- synchronized(dummy)
+ synchronized(sync)
{
if(listeners != null && listeners.size() > 0)
{
msg.append("Registered listener: ");
- Iterator it = listeners.keySet().iterator();
+ Iterator it = listeners.iterator();
boolean first = true;
while(it.hasNext())
{
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org