Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/DB2Factory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/DB2Factory.java (revision 8352) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/DB2Factory.java (working copy) @@ -91,7 +91,7 @@ } @Override - public String getIdentityQueryString(final String tableName, final String columnName) { + public String getIdentitySelectString(final String tableName, final String columnName) { return "SELECT IDENTITY_VAL_LOCAL() FROM sysibm.sysdummy1"; } @@ -114,6 +114,12 @@ return false; } + @Override + public String getSequenceBeforeSelectString(final String seqName, + final String tableName, final int increment) { + return "SELECT nextval FOR " + seqName + " FROM SYSIBM.SYSDUMMY1"; + } + //----------------------------------------------------------------------------------- } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/DerbyFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/DerbyFactory.java (revision 8352) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/DerbyFactory.java (working copy) @@ -90,7 +90,7 @@ } @Override - public String getIdentityQueryString(final String tableName, final String columnName) { + public String getIdentitySelectString(final String tableName, final String columnName) { return "SELECT IDENTITY_VAL_LOCAL() FROM " + quoteName(tableName); } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/GenericFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/GenericFactory.java (revision 8376) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/GenericFactory.java (working copy) @@ -113,7 +113,7 @@ /** * {@inheritDoc} */ - public String getIdentityQueryString(final String tableName, final String columnName) { + public String getIdentitySelectString(final String tableName, final String columnName) { throw new UnsupportedOperationException(); } @@ -138,6 +138,23 @@ return null; } + /** + * {@inheritDoc} + */ + public String getSequenceAfterSelectString(final String seqName, final String tableName) { + return "SELECT " + this.quoteName(seqName + ".currval") + + " FROM " + this.quoteName(tableName); + } + + /** + * {@inheritDoc} + */ + public String getSequenceBeforeSelectString(final String seqName, + final String tableName, final int increment) { + return "SELECT " + this.quoteName(seqName + ".currval") + " FROM " + + this.quoteName(tableName); + } + //----------------------------------------------------------------------------------- } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/HsqlFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/HsqlFactory.java (revision 8352) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/HsqlFactory.java (working copy) @@ -87,7 +87,7 @@ } @Override - public String getIdentityQueryString(final String tableName, final String columnName) { + public String getIdentitySelectString(final String tableName, final String columnName) { return "CALL IDENTITY()"; } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/InformixFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/InformixFactory.java (revision 8352) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/InformixFactory.java (working copy) @@ -88,7 +88,7 @@ } @Override - public String getIdentityQueryString(final String tableName, final String columnName) { + public String getIdentitySelectString(final String tableName, final String columnName) { return "select dbinfo('sqlca.sqlerrd1') from systables where tabid = 1"; } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/InterbaseFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/InterbaseFactory.java (revision 8352) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/InterbaseFactory.java (working copy) @@ -46,6 +46,12 @@ return false; } + @Override + public String getSequenceBeforeSelectString(final String seqName, + final String tableName, final int increment) { + return "SELECT gen_id(" + seqName + "," + increment + ") FROM rdb$database"; + } + //----------------------------------------------------------------------------------- } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/MySQLFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/MySQLFactory.java (revision 8352) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/MySQLFactory.java (working copy) @@ -109,7 +109,7 @@ } @Override - public String getIdentityQueryString(final String tableName, final String columnName) { + public String getIdentitySelectString(final String tableName, final String columnName) { return "SELECT LAST_INSERT_ID()"; } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/OracleFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/OracleFactory.java (revision 8376) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/OracleFactory.java (working copy) @@ -135,6 +135,12 @@ return seqName + ".nextval"; } + @Override + public String getSequenceBeforeSelectString(final String seqName, + final String tableName, final int increment) { + return "SELECT " + this.quoteName(seqName + ".nextval") + " FROM DUAL"; + } + //----------------------------------------------------------------------------------- } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/PointbaseFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/PointbaseFactory.java (revision 8352) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/PointbaseFactory.java (working copy) @@ -63,7 +63,7 @@ } @Override - public String getIdentityQueryString(final String tableName, final String columnName) { + public String getIdentitySelectString(final String tableName, final String columnName) { return "SELECT @@identity"; } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/PostgreSQLFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/PostgreSQLFactory.java (revision 8376) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/PostgreSQLFactory.java (working copy) @@ -130,7 +130,7 @@ } @Override - public String getIdentityQueryString(final String tableName, final String columnName) { + public String getIdentitySelectString(final String tableName, final String columnName) { // PostgreSQL uses a sequence in the background // name of the sequence is: __seq return "SELECT currval('\"" + tableName + "_" + columnName + "_seq\"')"; @@ -155,6 +155,17 @@ return false; } + @Override + public String getSequenceBeforeSelectString(final String seqName, + final String tableName, final int increment) { + return "SELECT nextval('\"" + seqName + "\"')"; + } + + @Override + public String getSequenceAfterSelectString(final String seqName, final String tableName) { + return "SELECT currval('\"" + seqName + "\"')"; + } + //----------------------------------------------------------------------------------- } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/SQLServerFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/SQLServerFactory.java (revision 8376) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/SQLServerFactory.java (working copy) @@ -127,7 +127,7 @@ } @Override - public String getIdentityQueryString(final String tableName, final String columnName) { + public String getIdentitySelectString(final String tableName, final String columnName) { return "SELECT @@identity"; } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/SapDbFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/SapDbFactory.java (revision 8376) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/SapDbFactory.java (working copy) @@ -184,7 +184,7 @@ } @Override - public String getIdentityQueryString(final String tableName, final String columnName) { + public String getIdentitySelectString(final String tableName, final String columnName) { return "SELECT " + quoteName(tableName) + ".currval" + " FROM " + quoteName(tableName); } @@ -207,6 +207,12 @@ return false; } + @Override + public String getSequenceBeforeSelectString(final String seqName, + final String tableName, final int increment) { + return "SELECT " + this.quoteName(seqName + ".nextval") + " FROM DUAL"; + } + //----------------------------------------------------------------------------------- } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/driver/SybaseFactory.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/driver/SybaseFactory.java (revision 8376) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/driver/SybaseFactory.java (working copy) @@ -115,7 +115,7 @@ } @Override - public String getIdentityQueryString(final String tableName, final String columnName) { + public String getIdentitySelectString(final String tableName, final String columnName) { return "SELECT @@identity"; } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/IdentityKeyGenerator.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/IdentityKeyGenerator.java (revision 8361) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/IdentityKeyGenerator.java (working copy) @@ -115,7 +115,7 @@ try { // prepares the statement - String sql = _factory.getIdentityQueryString(tableName, primKeyName); + String sql = _factory.getIdentitySelectString(tableName, primKeyName); stmt = conn.prepareStatement(sql); // execute the prepared statement Index: cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/NoKeyGenerator.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/NoKeyGenerator.java (revision 8376) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/NoKeyGenerator.java (working copy) @@ -28,7 +28,6 @@ import org.castor.cpa.persistence.sql.query.QueryContext; import org.castor.persist.ProposedEntity; import org.exolab.castor.jdo.Database; -import org.exolab.castor.jdo.DuplicateIdentityException; import org.exolab.castor.jdo.PersistenceException; import org.exolab.castor.jdo.engine.SQLColumnInfo; import org.exolab.castor.jdo.engine.SQLEngine; Index: cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/SequenceAfterKeyGenerator.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/SequenceAfterKeyGenerator.java (revision 8360) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/SequenceAfterKeyGenerator.java (working copy) @@ -27,7 +27,6 @@ import org.apache.commons.logging.LogFactory; import org.exolab.castor.jdo.PersistenceException; import org.castor.core.util.Messages; -import org.castor.cpa.persistence.sql.driver.PostgreSQLFactory; import org.exolab.castor.mapping.MappingException; import org.exolab.castor.persist.spi.PersistenceFactory; @@ -40,140 +39,9 @@ * @author Ralf Joachim * @version $Revision$ $Date: 2009-07-13 17:22:43 (Tue, 28 Jul 2009) $ */ -public final class SequenceAfterKeyGenerator extends AbstractAfterKeyGenerator { +public final class SequenceAfterKeyGenerator extends AbstractAfterKeyGenerator { //----------------------------------------------------------------------------------- - - /** - * Implements database engine specific subclasses which generates the - * database specific query systex for fetching ID from the database and then - * SequenceKeyGetValueHandler runs that query using JDBC connection. - */ - private abstract class SequenceKeyGenValueHandler { - - /** key generator for producing identities for objects after - * they are created in the database. - */ - private KeyGenerator _keyGenerator; - - /** Particular type handler instance. */ - private KeyGeneratorTypeHandler _typeHandler; - - /** Abstract method that must be implemented by subclasses of this class and - * responsible for running query to get identity. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * - * @return Identity. - * @throws Exception If fails to retrieve identity. - */ - protected abstract Object getValue(Connection conn, String tableName, - String primKeyName, Properties props) throws Exception; - - /** - * Method that runs sql query using the provided JDBC connection. - * - * @param sql A sql query - * @param conn An open JDBC connection - * - * @return Query results containing the identity value. - * @throws PersistenceException If fails to retrive identity value from resultset or - * database error occurs. - */ - public Object getValue(final String sql, final Connection conn) - throws PersistenceException { - PreparedStatement stmt = null; - try { - stmt = conn.prepareStatement(sql); - ResultSet rs = stmt.executeQuery(); - return _typeHandler.getValue(rs); - } catch (SQLException e) { - String msg = Messages.format("persist.keyGenSQL", - _keyGenerator.getClass().getName(), e.toString()); - throw new PersistenceException(msg); - } finally { - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException ex) { - ex.printStackTrace(); - } - } - } - } - - /** - * Sets the KeyGenerator instance value. - * - * @param generator Provided keyGenerator instance. - */ - public void setGenerator(final KeyGenerator generator) { - _keyGenerator = generator; - } - - /** - * Sets typeHandler object with the value provided. - * - * @param typeHandler Provided typeHandler instance. - */ - public void setTypeHandler(final KeyGeneratorTypeHandler typeHandler) { - _typeHandler = typeHandler; - } - } - - /** - * Implements SequenceKeyGenValueHandler that generates sql query used as - * a default query except for the particular database engine types. - */ - private class DefaultType extends SequenceKeyGenValueHandler { - - /** - * Generates sql select query for fetching identity and then calss the - * base class getValue method of query execution. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * @return ResutlSet containing identity. - * @throws Exception If database error occurs. - */ - protected Object getValue(final Connection conn, final String tableName, - final String primKeyName, final Properties props) throws Exception { - return getValue("SELECT " - + _factory.quoteName(getSeqName(tableName, primKeyName) + ".currval") - + " FROM " + _factory.quoteName(tableName), conn); - } - } - /** - * Implements SequenceKeyGenValueHandler that generates sql query for fetching - * identity from Postgressql database. - */ - private class PostgresqlType extends SequenceKeyGenValueHandler { - - /** - * Generates sql select query for fetching identity and then calss the - * base class getValue method of query execution. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * @return ResutlSet containing identity. - * @throws Exception If database error occurs. - */ - protected Object getValue(final Connection conn, final String tableName, - final String primKeyName, final Properties props) throws Exception { - String sql = "SELECT currval('\"" + getSeqName(tableName, primKeyName) + "\"')"; - return getValue(sql, conn); - } - } - - //----------------------------------------------------------------------------------- - /** The Jakarta * Commons Logging instance used for all logging. */ private static final Log LOG = LogFactory.getLog(SequenceAfterKeyGenerator.class); @@ -191,9 +59,6 @@ /** Particular type handler instance. */ private KeyGeneratorTypeHandler _typeHandler; - /** Sequence Key handler type. */ - private SequenceKeyGenValueHandler _type = null; - //----------------------------------------------------------------------------------- /** @@ -214,7 +79,6 @@ _seqName = params.getProperty("sequence", "{0}_seq"); initSqlTypeHandler(sqlType); - initType(); } /** @@ -245,18 +109,6 @@ return MessageFormat.format(_seqName, new Object[] {tableName, primKeyName}); } - /** Instantiate class properties i.e type and typeHandler based on the - * factory type. */ - private void initType() { - if (PostgreSQLFactory.FACTORY_NAME.equals(_factory.getFactoryName())) { - _type = new PostgresqlType(); - } else { - _type = new DefaultType(); - } - _type.setGenerator(this); - _type.setTypeHandler(_typeHandler); - } - //----------------------------------------------------------------------------------- /** @@ -269,11 +121,31 @@ */ public Object generateKey(final Connection conn, final String tableName, final String primKeyName, final Properties props) throws PersistenceException { + PreparedStatement stmt = null; + ResultSet rs = null; + try { - return _type.getValue(conn, tableName, primKeyName, props); - } catch (Exception e) { - LOG.error("Problem generating new key", e); - throw new PersistenceException(Messages.format("persist.keyGenSQL", e)); + // prepares the statement + String sql = _factory.getSequenceAfterSelectString( + getSeqName(tableName, primKeyName), tableName); + stmt = conn.prepareStatement(sql); + + // execute the prepared statement + rs = stmt.executeQuery(); + + // process result set using appropriate handler and return its value + return _typeHandler.getValue(rs); + } catch (SQLException e) { + String msg = Messages.format("persist.keyGenSQL", + this.getClass().getName(), e.toString()); + throw new PersistenceException(msg); + } finally { + try { + if (rs != null) { rs.close(); } + if (stmt != null) { stmt.close(); } + } catch (SQLException e) { + LOG.warn("Problem closing JDBC statement", e); + } } } Index: cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/SequenceBeforeKeyGenerator.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/SequenceBeforeKeyGenerator.java (revision 8376) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/SequenceBeforeKeyGenerator.java (working copy) @@ -27,11 +27,6 @@ import org.apache.commons.logging.LogFactory; import org.exolab.castor.jdo.PersistenceException; import org.castor.core.util.Messages; -import org.castor.cpa.persistence.sql.driver.DB2Factory; -import org.castor.cpa.persistence.sql.driver.SapDbFactory; -import org.castor.cpa.persistence.sql.driver.InterbaseFactory; -import org.castor.cpa.persistence.sql.driver.PostgreSQLFactory; -import org.castor.cpa.persistence.sql.driver.OracleFactory; import org.exolab.castor.mapping.MappingException; import org.exolab.castor.persist.spi.PersistenceFactory; @@ -44,238 +39,9 @@ * @author Ralf Joachim * @version $Revision$ $Date: 2009-07-13 17:22:43 (Tue, 28 Jul 2009) $ */ -public final class SequenceBeforeKeyGenerator extends AbstractBeforeKeyGenerator { +public final class SequenceBeforeKeyGenerator extends AbstractBeforeKeyGenerator { //----------------------------------------------------------------------------------- - - /** - * Implements database engine specific subclasses which generates the - * database specific query systex for fetching ID from the database and then - * SequenceKeyGetValueHandler runs that query using JDBC connection. - */ - private abstract class SequenceKeyGenValueHandler { - - /** key generator for producing identities for objects after - * they are created in the database. - */ - private KeyGenerator _keyGenerator; - - /** Particular type handler instance. */ - private KeyGeneratorTypeHandler _typeHandler; - - /** Abstract method that must be implemented by subclasses of this class and - * responsible for running query to get identity. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * - * @return Identity. - * @throws Exception If fails to retrieve identity. - */ - protected abstract Object getValue(Connection conn, String tableName, - String primKeyName, Properties props) throws Exception; - - /** - * Method that runs sql query using the provided JDBC connection. - * - * @param sql A sql query - * @param conn An open JDBC connection - * - * @return Query results containing the identity value. - * @throws PersistenceException If fails to retrive identity value from resultset or - * database error occurs. - */ - public Object getValue(final String sql, final Connection conn) - throws PersistenceException { - PreparedStatement stmt = null; - try { - stmt = conn.prepareStatement(sql); - ResultSet rs = stmt.executeQuery(); - return _typeHandler.getValue(rs); - } catch (SQLException e) { - String msg = Messages.format("persist.keyGenSQL", - _keyGenerator.getClass().getName(), e.toString()); - throw new PersistenceException(msg); - } finally { - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException ex) { - ex.printStackTrace(); - } - } - } - } - - /** - * Sets the KeyGenerator instance value. - * - * @param generator Provided keyGenerator instance. - */ - public void setGenerator(final KeyGenerator generator) { - _keyGenerator = generator; - } - - /** - * Sets typeHandler object with the value provided. - * - * @param typeHandler Provided typeHandler instance. - */ - public void setTypeHandler(final KeyGeneratorTypeHandler typeHandler) { - _typeHandler = typeHandler; - } - } - - /** - * Implements SequenceKeyGenValueHandler that generates sql query used as - * a default query except for the particular database engine types. - */ - private class DefaultType extends SequenceKeyGenValueHandler { - - /** - * Generates sql select query for fetching identity and then calss the - * base class getValue method of query execution. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * @return ResutlSet containing identity. - * @throws Exception If database error occurs. - */ - protected Object getValue(final Connection conn, final String tableName, - final String primKeyName, final Properties props) throws Exception { - return getValue("SELECT " - + _factory.quoteName(getSeqName(tableName, primKeyName) + ".currval") - + " FROM " + _factory.quoteName(tableName), conn); - } - } - /** - * Implements SequenceKeyGenValueHandler that generates sql query for fetching - * identity from Postgressql database. - */ - private class PostgresqlType extends SequenceKeyGenValueHandler { - - /** - * Generates sql select query for fetching identity and then calss the - * base class getValue method of query execution. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * @return ResutlSet containing identity. - * @throws Exception If database error occurs. - */ - protected Object getValue(final Connection conn, final String tableName, - final String primKeyName, final Properties props) throws Exception { - String sql = "SELECT nextval('\"" + getSeqName(tableName, primKeyName) + "\"')"; - return getValue(sql, conn); - } - } - - /** - * Implements SequenceKeyGenValueHandler that generates sql query for fetching - * identity from DB2 database. - */ - private class DB2Type extends SequenceKeyGenValueHandler { - - /** - * Generates sql select query for fetching identity and then calss the - * base class getValue method of query execution. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * @return ResutlSet containing identity. - * @throws Exception If database error occurs. - */ - protected Object getValue(final Connection conn, final String tableName, - final String primKeyName, final Properties props) throws Exception { - return getValue("SELECT nextval FOR " + getSeqName(tableName, primKeyName) - + " FROM SYSIBM.SYSDUMMY1", conn); - } - } - - /** - * Implements SequenceKeyGenValueHandler that generates sql query for fetching - * identity from Interbase database. - */ - private class InterbaseType extends SequenceKeyGenValueHandler { - - /** - * Generates sql select query for fetching identity and then calss the - * base class getValue method of query execution. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * @return ResutlSet containing identity. - * @throws Exception If database error occurs. - */ - protected Object getValue(final Connection conn, final String tableName, - final String primKeyName, final Properties props) throws Exception { - return getValue("SELECT gen_id(" + getSeqName(tableName, primKeyName) + "," - + _increment + ") FROM rdb$database", conn); - } - } - - /** - * Implements SequenceKeyGenValueHandler that generates sql query for fetching - * identity from oracle database. - */ - private class OracleType extends SequenceKeyGenValueHandler { - - /** - * Generates sql select query for fetching identity and then calss the - * base class getValue method of query execution. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * @return ResutlSet containing identity. - * @throws Exception If database error occurs. - */ - protected Object getValue(final Connection conn, final String tableName, - final String primKeyName, final Properties props) throws Exception { - return getValue("SELECT " - + _factory.quoteName(getSeqName(tableName, primKeyName) + ".nextval") - + " FROM DUAL", conn); - } - } - - /** - * Implements SequenceKeyGenValueHandler that generates sql query for fetching - * identity from sap/max database. - */ - private class SapDbType extends SequenceKeyGenValueHandler { - - /** - * Generates sql select query for fetching identity and then calss the - * base class getValue method of query execution. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * @return ResutlSet containing identity. - * @throws Exception If database error occurs. - */ - protected Object getValue(final Connection conn, final String tableName, - final String primKeyName, final Properties props) throws Exception { - return getValue("SELECT " - + _factory.quoteName(getSeqName(tableName, primKeyName) + ".nextval") - + " FROM DUAL", conn); - } - } - - //----------------------------------------------------------------------------------- - /** The Jakarta * Commons Logging instance used for all logging. */ private static final Log LOG = LogFactory.getLog(SequenceBeforeKeyGenerator.class); @@ -296,9 +62,6 @@ /** Particular type handler instance. */ private KeyGeneratorTypeHandler _typeHandler; - /** Sequence Key Handler type. */ - private SequenceKeyGenValueHandler _type = null; - //----------------------------------------------------------------------------------- /** @@ -324,7 +87,6 @@ } initSqlTypeHandler(sqlType); - initType(); } /** @@ -355,27 +117,6 @@ return MessageFormat.format(_seqName, new Object[] {tableName, primKeyName}); } - /** Instantiate class properties i.e type and typeHandler based on the - * factory type. */ - private void initType() { - String factoryName = _factory.getFactoryName(); - if (InterbaseFactory.FACTORY_NAME.equals(factoryName)) { - _type = new InterbaseType(); - } else if (DB2Factory.FACTORY_NAME.equals(factoryName)) { - _type = new DB2Type(); - } else if (PostgreSQLFactory.FACTORY_NAME.equals(factoryName)) { - _type = new PostgresqlType(); - } else if (OracleFactory.FACTORY_NAME.equals(factoryName)) { - _type = new OracleType(); - } else if (SapDbFactory.FACTORY_NAME.equals(factoryName)) { - _type = new SapDbType(); - } else { - _type = new DefaultType(); - } - _type.setGenerator(this); - _type.setTypeHandler(_typeHandler); - } - //----------------------------------------------------------------------------------- /** @@ -387,13 +128,34 @@ * @throws PersistenceException An error occured talking to persistent storage. */ public Object generateKey(final Connection conn, final String tableName, - final String primKeyName, final Properties props) throws PersistenceException { - try { - return _type.getValue(conn, tableName, primKeyName, props); - } catch (Exception e) { - LOG.error("Problem generating new key", e); - throw new PersistenceException(Messages.format("persist.keyGenSQL", e)); - } + final String primKeyName, final Properties props) + throws PersistenceException { + PreparedStatement stmt = null; + ResultSet rs = null; + + try { + // prepares the statement + String sql = _factory.getSequenceBeforeSelectString( + getSeqName(tableName, primKeyName), tableName, _increment); + stmt = conn.prepareStatement(sql); + + // execute the prepared statement + rs = stmt.executeQuery(); + + // process result set using appropriate handler and return its value + return _typeHandler.getValue(rs); + } catch (SQLException e) { + String msg = Messages.format("persist.keyGenSQL", + this.getClass().getName(), e.toString()); + throw new PersistenceException(msg); + } finally { + try { + if (rs != null) { rs.close(); } + if (stmt != null) { stmt.close(); } + } catch (SQLException e) { + LOG.warn("Problem closing JDBC statement", e); + } + } } /** Index: cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/SequenceDuringKeyGenerator.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/SequenceDuringKeyGenerator.java (revision 8376) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/keygen/SequenceDuringKeyGenerator.java (working copy) @@ -18,10 +18,7 @@ import java.sql.Connection; import java.sql.CallableStatement; import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Types; -import java.text.MessageFormat; import java.util.Properties; import org.apache.commons.logging.Log; @@ -31,12 +28,10 @@ import org.exolab.castor.mapping.MappingException; import org.exolab.castor.persist.spi.PersistenceFactory; import org.exolab.castor.jdo.Database; -import org.exolab.castor.jdo.DuplicateIdentityException; import org.exolab.castor.jdo.engine.SQLColumnInfo; import org.exolab.castor.jdo.engine.SQLEngine; import org.exolab.castor.jdo.engine.SQLFieldInfo; import org.exolab.castor.jdo.engine.nature.ClassDescriptorJDONature; -import org.castor.cpa.persistence.sql.engine.SQLStatementInsertCheck; import org.castor.cpa.persistence.sql.query.Insert; import org.castor.cpa.persistence.sql.query.QueryContext; import org.castor.persist.ProposedEntity; @@ -53,120 +48,10 @@ */ public final class SequenceDuringKeyGenerator extends AbstractKeyGenerator { //----------------------------------------------------------------------------------- - - /** - * Implements database engine specific subclasses which generates the - * database specific query systex for fetching ID from the database and then - * SequenceKeyGetValueHandler runs that query using JDBC connection. - */ - private abstract class SequenceKeyGenValueHandler { - - /** key generator for producing identities for objects after - * they are created in the database. - */ - private KeyGenerator _keyGenerator; - - /** Particular type handler instance. */ - private KeyGeneratorTypeHandler _typeHandler; - - /** Abstract method that must be implemented by subclasses of this class and - * responsible for running query to get identity. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * - * @return Identity. - * @throws Exception If fails to retrieve identity. - */ - protected abstract Object getValue(Connection conn, String tableName, - String primKeyName, Properties props) throws Exception; - - /** - * Method that runs sql query using the provided JDBC connection. - * - * @param sql A sql query - * @param conn An open JDBC connection - * - * @return Query results containing the identity value. - * @throws PersistenceException If fails to retrive identity value from resultset or - * database error occurs. - */ - public Object getValue(final String sql, final Connection conn) - throws PersistenceException { - PreparedStatement stmt = null; - try { - stmt = conn.prepareStatement(sql); - ResultSet rs = stmt.executeQuery(); - return _typeHandler.getValue(rs); - } catch (SQLException e) { - String msg = Messages.format("persist.keyGenSQL", - _keyGenerator.getClass().getName(), e.toString()); - throw new PersistenceException(msg); - } finally { - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException ex) { - ex.printStackTrace(); - } - } - } - } - - /** - * Sets the KeyGenerator instance value. - * - * @param generator Provided keyGenerator instance. - */ - public void setGenerator(final KeyGenerator generator) { - _keyGenerator = generator; - } - - /** - * Sets typeHandler object with the value provided. - * - * @param typeHandler Provided typeHandler instance. - */ - public void setTypeHandler(final KeyGeneratorTypeHandler typeHandler) { - _typeHandler = typeHandler; - } - } - - /** - * Implements SequenceKeyGenValueHandler that generates sql query used as - * a default query except for the particular database engine types. - */ - private class DefaultType extends SequenceKeyGenValueHandler { - /** - * Generates sql select query for fetching identity and then calss the - * base class getValue method of query execution. - * - * @param conn An open JDBC connection. - * @param tableName Name of the table from which identity will be fetched. - * @param primKeyName Primary key of the table. - * @param props database engine specific properties. - * @return ResutlSet containing identity. - * @throws Exception If database error occurs. - */ - protected Object getValue(final Connection conn, final String tableName, - final String primKeyName, final Properties props) throws Exception { - // used for orcale and sap after_insert - return getValue("SELECT " - + _factory.quoteName(getSeqName(tableName, primKeyName) + ".currval") - + " FROM " + _factory.quoteName(tableName), conn); - } - } - //----------------------------------------------------------------------------------- - /** The Jakarta * Commons Logging instance used for all logging. */ private static final Log LOG = LogFactory.getLog(SequenceDuringKeyGenerator.class); - - /** Key length used for KeyGeneratorTypeHandlerString. */ - private static final int STRING_KEY_LENGTH = 8; /** Persistence factory for the database engine the entity is persisted in. * Used to format the SQL statement. */ @@ -178,19 +63,10 @@ /** Sequence name associated with the table. */ private String _seqName; - /** Particular type handler instance. */ - private KeyGeneratorTypeHandler _typeHandler; - - /** Databse engine type. */ - private SequenceKeyGenValueHandler _type = null; - /** SQL engine for all persistence operations at entities of the type this * class is responsible for. Holds all required information of the entity type. */ private SQLEngine _engine; - /** An sql statement. */ - // private String _statement; - /** Name of the Table extracted from Class descriptor. */ private String _mapTo; @@ -218,48 +94,9 @@ _factory = factory; _triggerPresent = "true".equals(params.getProperty("trigger", "false")); _seqName = params.getProperty("sequence", "{0}_seq"); - _ctx = new QueryContext(_factory); - - initSqlTypeHandler(sqlType); - initType(); + _ctx = new QueryContext(_factory); } - - /** - * Initialize the Handler based on SQL Type. - * - * @param sqlType A SQLTypidentifier. - */ - protected void initSqlTypeHandler(final int sqlType) { - if (sqlType == Types.INTEGER) { - _typeHandler = new KeyGeneratorTypeHandlerInteger(true); - } else if (sqlType == Types.BIGINT) { - _typeHandler = new KeyGeneratorTypeHandlerLong(true); - } else if ((sqlType == Types.CHAR) || (sqlType == Types.VARCHAR)) { - _typeHandler = new KeyGeneratorTypeHandlerString(true, STRING_KEY_LENGTH); - } else { - _typeHandler = new KeyGeneratorTypeHandlerBigDecimal(true); - } - } - /** - * Formats the sequence name using name of the table and ID. - * - * @param tableName Name of the table. - * @param primKeyName ID of the table. - * @return Strign representing formatted sequence name. - */ - private String getSeqName(final String tableName, final String primKeyName) { - return MessageFormat.format(_seqName, new Object[] {tableName, primKeyName}); - } - - /** Instantiate class properties i.e type and typeHandler based on the - * factory type. */ - private void initType() { - _type = new DefaultType(); - _type.setGenerator(this); - _type.setTypeHandler(_typeHandler); - } - //----------------------------------------------------------------------------------- /** @@ -272,12 +109,7 @@ */ public Object generateKey(final Connection conn, final String tableName, final String primKeyName, final Properties props) throws PersistenceException { - try { - return _type.getValue(conn, tableName, primKeyName, props); - } catch (Exception e) { - LOG.error("Problem generating new key", e); - throw new PersistenceException(Messages.format("persist.keyGenSQL", e)); - } + return null; } /** @@ -314,7 +146,7 @@ } } SQLColumnInfo[] ids = _engine.getColumnInfoForIdentities(); - //_statement = this.patchSQL(_statement, ids[0].getName()); + if (!_triggerPresent) { insert.addInsert(ids[0].getName(), _seqName); } @@ -332,7 +164,6 @@ */ public Object executeStatement(final Database database, final Connection conn, final Identity identity, final ProposedEntity entity) throws PersistenceException { - SQLStatementInsertCheck lookupStatement = new SQLStatementInsertCheck(_engine, _factory); Identity internalIdentity = identity; SQLEngine extended = _engine.getExtends(); Index: cpa/src/main/java/org/exolab/castor/persist/spi/PersistenceFactory.java =================================================================== --- cpa/src/main/java/org/exolab/castor/persist/spi/PersistenceFactory.java (revision 8376) +++ cpa/src/main/java/org/exolab/castor/persist/spi/PersistenceFactory.java (working copy) @@ -160,7 +160,7 @@ * @param columnName Name of the column from which identity needs to be fetched. * @return SQL Query string for fetching the identity value. */ - String getIdentityQueryString(final String tableName, final String columnName); + String getIdentitySelectString(final String tableName, final String columnName); /** * Does persistence factory support generation of new key at the time of new @@ -189,7 +189,29 @@ * @return String to fetch sequence next value. */ String getSequenceNextValString(String seqName); + + /** + * Returns the database specific SELECT query string + * for fetching identity before the next INSERT statement gets executed. + * + * @param seqName Name of sequence. + * @param tableName Name of the table from which identity will be fetched. + * @param increment Increment value used in Interbase database engine. + * @return SELECT sql string + */ + String getSequenceBeforeSelectString(String seqName, + String tableName, int increment); + /** + * Returns the database specific SELECT query string + * for fetching identity after the INSERT statement executed. + * + * @param seqName Name of sequence. + * @param tableName Name of the table from which identity will be fetched. + * @return SELECT sql string + */ + String getSequenceAfterSelectString(String seqName, String tableName); + //----------------------------------------------------------------------------------- } Index: src/doc/release-notes.xml =================================================================== --- src/doc/release-notes.xml (revision 8376) +++ src/doc/release-notes.xml (working copy) @@ -91,6 +91,26 @@ ]]> + + + Move Database specific code from KeyGenerators to PersistenceFactory. + + + Ahmad Hassan + ahmad.hassan@gmail.com + + + Ralf Joachim + ralf.joachim@syscon.eu + + + Ahmad Hassan + ahmad.hassan@gmail.com + + Bug + JDO + 20090819 + Sequence key generator on MaxDB generates wrong command.