Index: cpa/src/main/java/org/castor/cpa/persistence/sql/engine/SQLStatementUpdate.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/engine/SQLStatementUpdate.java (revision 8289) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/engine/SQLStatementUpdate.java (working copy) @@ -24,7 +24,6 @@ import org.castor.cpa.persistence.sql.query.Update; import org.castor.cpa.persistence.sql.query.QueryContext; import org.castor.cpa.persistence.sql.query.condition.AndCondition; -import org.castor.cpa.persistence.sql.query.QueryConstants; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.castor.core.util.Messages; @@ -94,19 +93,16 @@ * class is responsible for. Holds all required information of the entity type. * @param factory Persistence factory for the database engine the entity is persisted in. * Used to format the SQL statement. - * @param load */ - public SQLStatementUpdate(final SQLEngine engine, final PersistenceFactory factory, - final String load) { + public SQLStatementUpdate(final SQLEngine engine, final PersistenceFactory factory) { _type = engine.getDescriptor().getJavaClass().getName(); _ids = engine.getColumnInfoForIdentities(); _fields = engine.getInfo(); - _factory = factory; buildStatement(new ClassDescriptorJDONature(engine.getDescriptor()).getTableName()); - _statementUpdateCheck = new SQLStatementUpdateCheck(engine, load); + _statementUpdateCheck = new SQLStatementUpdateCheck(engine, factory); } /** @@ -259,6 +255,8 @@ * Prepares the SQL Statement. * * @param conn An Open JDBC Connection + * @param ctx QueryContext for SQL query building, specifying database specific quotations + * and parameters binding. * @throws SQLException If a database access error occurs. */ private void prepareStatement(final Connection conn, final QueryContext ctx) @@ -277,6 +275,8 @@ * Binds new entities. * * @param newentity + * @param ctx QueryContext for SQL query building, specifying database specific quotations + * and parameters binding. * @throws PersistenceException If identity size mismatches * or column length mismatches * @throws SQLException If database access error occurs @@ -326,6 +326,8 @@ * Binds Identity. * * @param identity + * @param ctx QueryContext for SQL query building, specifying database specific quotations + * and parameters binding. * @throws PersistenceException If identity size mismatches * or column length mismatches * @throws SQLException If database access error occurs @@ -351,6 +353,8 @@ * Binds old Entities. * * @param oldentity + * @param ctx QueryContext for SQL query building, specifying database specific quotations + * and parameters binding. * @throws PersistenceException If identity size mismatches * or column length mismatches * @throws SQLException If database access error occurs Index: cpa/src/main/java/org/castor/cpa/persistence/sql/engine/SQLStatementUpdateCheck.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/engine/SQLStatementUpdateCheck.java (revision 8289) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/engine/SQLStatementUpdateCheck.java (working copy) @@ -25,15 +25,16 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.castor.core.util.Messages; +import org.castor.cpa.persistence.sql.query.QueryConstants; import org.castor.persist.ProposedEntity; import org.exolab.castor.jdo.ObjectDeletedException; import org.exolab.castor.jdo.ObjectModifiedException; import org.exolab.castor.jdo.PersistenceException; 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.exolab.castor.persist.spi.Identity; +import org.exolab.castor.persist.spi.PersistenceFactory; /** * SQLStatementUpdatCheck class to check whether the new SQL Update statement has @@ -56,31 +57,61 @@ /** The name of engine descriptor. */ private final String _type; - /** Table name of the engine descriptor. */ - private final String _mapTo; - - /** The SQL statement for update failure reason check. */ - private final String _statement; - /** Column information for identities specific to the particular engine instance. */ private final SQLColumnInfo[] _ids; - /** Contains the Information specific to particular engine instancde. */ - private final SQLFieldInfo[] _fields; + /** Persistence factory for the database engine the entity is persisted in. + * Used to format the SQL statement. */ + private final PersistenceFactory _factory; + + /** The SQL statement for update failure reason check. */ + private String _statement; /** * Constructor. * * @param engine SQL engine for all persistence operations at entities of the type this * class is responsible for. Holds all required information of the entity type. - * @param statement SQL statement to check the previously updated/modified record. */ - public SQLStatementUpdateCheck(final SQLEngine engine, final String statement) { - _statement = statement; + public SQLStatementUpdateCheck(final SQLEngine engine, final PersistenceFactory factory) { _type = engine.getDescriptor().getJavaClass().getName(); - _mapTo = new ClassDescriptorJDONature(engine.getDescriptor()).getTableName(); _ids = engine.getColumnInfoForIdentities(); - _fields = engine.getInfo(); + _factory = factory; + + buildStatement(new ClassDescriptorJDONature(engine.getDescriptor()).getTableName()); + } + + private void buildStatement(final String mapTo) { + StringBuilder sb = new StringBuilder(); + + sb.append(QueryConstants.SELECT); + sb.append(QueryConstants.SPACE); + sb.append(_factory.quoteName(mapTo)); + sb.append(QueryConstants.DOT); + sb.append(_factory.quoteName(_ids[0].getName())); + sb.append(QueryConstants.SPACE); + sb.append(QueryConstants.FROM); + sb.append(QueryConstants.SPACE); + sb.append(_factory.quoteName(mapTo)); + sb.append(QueryConstants.SPACE); + sb.append(QueryConstants.WHERE); + sb.append(QueryConstants.SPACE); + + for (int i = 0; i < _ids.length; i++) { + if (i != 0) { + sb.append(QueryConstants.SPACE); + sb.append(QueryConstants.AND); + sb.append(QueryConstants.SPACE); + } + + sb.append(_factory.quoteName(mapTo)); + sb.append(QueryConstants.DOT); + sb.append(_factory.quoteName(_ids[i].getName())); + sb.append(QueryConstants.ASSIGN); + sb.append(QueryConstants.PARAMETER); + } + + _statement = sb.toString(); } /** @@ -99,20 +130,20 @@ public void updateFailureCheck(final Connection conn, final Identity identity, final ProposedEntity oldentity) throws PersistenceException { try { - if (oldentity.getFields() != null) { prepareStatement(conn); - + //Binds identity bindIdentity(identity); - + //Load Data into resultset ResultSet resultSet = executeQuery(); - - //Process Resultset data - processData(identity, oldentity, resultSet); - } - throw new ObjectDeletedException(Messages.format( - "persist.objectDeleted", _type, identity)); + + if (resultSet.next()) { + String msg = Messages.format("persist.objectModified", _type, identity); + throw new ObjectModifiedException(msg); + } + String msg = Messages.format("persist.objectDeleted", _type, identity); + throw new ObjectDeletedException(msg); } catch (SQLException except) { LOG.fatal(Messages.format("jdo.updateCheckFatal", _type, _statement), except); throw new PersistenceException(Messages.format("persist.nested", except), except); @@ -120,7 +151,6 @@ //close statement closeStatement(); } - } /** @@ -129,7 +159,7 @@ * @param conn An Open JDBC Connection * @throws SQLException If a database access error occurs. */ - private void prepareStatement (final Connection conn) + private void prepareStatement(final Connection conn) throws SQLException { PreparedStatement preparedStatement = conn.prepareStatement(_statement); @@ -149,7 +179,7 @@ * or column length mismatches * @throws SQLException If database access error occurs */ - private void bindIdentity (final Identity identity) + private void bindIdentity(final Identity identity) throws PersistenceException, SQLException { // get prepared statement from thread local variable PreparedStatement preparedStatement = PREPARED_STATEMENT.get(); @@ -181,53 +211,6 @@ } /** - * process the ResultSet. - * - * @param identity - * @param oldentity - * @param resultSet containing the query results - * @throws SQLException If a database access error occurs - * @throws ObjectModifiedException Exception raised if object has been modified - * previously in the Persistence Storage - */ - private void processData (final Identity identity, final ProposedEntity oldentity, - final ResultSet resultSet) throws SQLException, ObjectModifiedException { - if (resultSet.next()) { - StringBuffer enlistFieldsNotMatching = new StringBuffer(); - - int numberOfFieldsNotMatching = 0; - for (int i = 0; i < _fields.length; i++) { - SQLColumnInfo[] columns = _fields[i].getColumnInfo(); - Object value = oldentity.getField(i); - Object currentField = columns[0].toJava(resultSet.getObject( - columns[0].getName())); - if (_fields[i].getTableName().compareTo(_mapTo) == 0) { - if ((value == null) || ((value != null) - && (currentField == null))) { - enlistFieldsNotMatching.append("(" + _type + ")." - + columns[0].getName() + ": "); - enlistFieldsNotMatching.append("[" + value + "/" - + currentField + "]"); - } else if (!value.equals(currentField)) { - if (numberOfFieldsNotMatching >= 1) { - enlistFieldsNotMatching.append(", "); - } - enlistFieldsNotMatching.append("(" + _type + ")." - + columns[0].getName() + ": "); - enlistFieldsNotMatching.append("[" + value + "/" - + currentField + "]"); - numberOfFieldsNotMatching++; - } - } - } - - throw new ObjectModifiedException(Messages.format( - "persist.objectModified", _type, identity, - enlistFieldsNotMatching.toString())); - } - } - - /** * closes the opened statement. */ private void closeStatement() { Index: cpa/src/main/java/org/castor/cpa/persistence/sql/query/QueryConstants.java =================================================================== --- cpa/src/main/java/org/castor/cpa/persistence/sql/query/QueryConstants.java (revision 8285) +++ cpa/src/main/java/org/castor/cpa/persistence/sql/query/QueryConstants.java (working copy) @@ -25,6 +25,9 @@ public final class QueryConstants { //----------------------------------------------------------------------------------- + /** 'SELECT' keyword of a SQL delete query. */ + public static final String SELECT = "SELECT"; + /** 'DELETE' keyword of a SQL delete query. */ public static final String DELETE = "DELETE"; Index: cpa/src/main/java/org/exolab/castor/jdo/engine/SQLEngine.java =================================================================== --- cpa/src/main/java/org/exolab/castor/jdo/engine/SQLEngine.java (revision 8289) +++ cpa/src/main/java/org/exolab/castor/jdo/engine/SQLEngine.java (working copy) @@ -187,7 +187,7 @@ _loadStatement = new SQLStatementLoad(this, factory); _createStatement = new SQLStatementCreate(this, factory); _removeStatement = new SQLStatementDelete(this, factory); - _storeStatement = new SQLStatementUpdate(this, factory, _loadStatement.getLoadStatement()); + _storeStatement = new SQLStatementUpdate(this, factory); } public SQLColumnInfo[] getColumnInfoForIdentities() { Index: src/doc/release-notes.xml =================================================================== --- src/doc/release-notes.xml (revision 8297) +++ src/doc/release-notes.xml (working copy) @@ -91,6 +91,26 @@ ]]> + + + Construct SQL SELECT Query inside SQLStatementUpdateCheck. + + + Ahmad Hassan + ahmad.hassan@gmail.com + + + Ralf Joachim + ralf.joachim@syscon.eu + + + Ahmad Hassan + ahmad.hassan@gmail.com + + Enh. + JDO + 20090727 + Split SequenceKeyGenerator into 3 implementations handling one of the Index: xml/src/main/resources/org/castor/messages.properties =================================================================== --- xml/src/main/resources/org/castor/messages.properties (revision 8278) +++ xml/src/main/resources/org/castor/messages.properties (working copy) @@ -210,9 +210,7 @@ persist.objectModified=\ Transaction aborted: Object of type {0} with identity {1} has been \ modified by a concurrent transaction \ - (cache entry is different from database row). \ - The following fields have been changed [actual/expected value]: \ - {2} + (cache entry is different from database row). persist.objectNotPersistent=\ The object of type {0} is not persistent -- it was not queried or \ created within this transaction