You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2008/01/24 02:33:53 UTC

svn commit: r614763 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ openjpa-kernel/src/main/java/org...

Author: fancy
Date: Wed Jan 23 17:33:48 2008
New Revision: 614763

URL: http://svn.apache.org/viewvc?rev=614763&view=rev
Log:
OPENJPA-477 Making StoreManager more flexible and extensible

Modified:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCBrokerFactory.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedStatementManagerImpl.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SQLStoreQuery.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowImpl.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Bootstrap.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java Wed Jan 23 17:33:48 2008
@@ -181,7 +181,7 @@
     /**
      * Recursive method to insert the given instance, base class first.
      */
-    private void insert(OpenJPAStateManager sm, ClassMapping mapping,
+    protected void insert(OpenJPAStateManager sm, ClassMapping mapping,
         RowManager rowMgr, JDBCStore store, Collection customs)
         throws SQLException {
         Boolean custom = mapping.isCustomInsert(sm, store);
@@ -228,7 +228,7 @@
     /**
      * Recursive method to delete the given instance, base class last.
      */
-    private void delete(OpenJPAStateManager sm, ClassMapping mapping,
+    protected void delete(OpenJPAStateManager sm, ClassMapping mapping,
         RowManager rowMgr, JDBCStore store, Collection customs)
         throws SQLException {
         Boolean custom = mapping.isCustomDelete(sm, store);
@@ -271,7 +271,7 @@
     /**
      * Recursive method to update the given instance.
      */
-    private void update(OpenJPAStateManager sm, BitSet dirty,
+    protected void update(OpenJPAStateManager sm, BitSet dirty,
         ClassMapping mapping, RowManager rowMgr, JDBCStore store,
         Collection customs) throws SQLException {
         Boolean custom = mapping.isCustomUpdate(sm, store);
@@ -300,7 +300,7 @@
     /**
      * Update version and discriminator indicators.
      */
-    private void updateIndicators(OpenJPAStateManager sm, ClassMapping mapping,
+    protected void updateIndicators(OpenJPAStateManager sm, ClassMapping mapping,
         RowManager rowMgr, JDBCStore store, Collection customs,
         boolean versionUpdateOnly) throws SQLException {
         while (mapping.getJoinablePCSuperclassMapping() != null)

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCBrokerFactory.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCBrokerFactory.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCBrokerFactory.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCBrokerFactory.java Wed Jan 23 17:33:48 2008
@@ -140,7 +140,7 @@
     /**
      * Synchronize the mappings of the classes listed in the configuration.
      */
-    private void synchronizeMappings(ClassLoader loader) {
+    protected void synchronizeMappings(ClassLoader loader) {
         JDBCConfiguration conf = (JDBCConfiguration) getConfiguration();
         String action = conf.getSynchronizeMappings();
         if (StringUtils.isEmpty(action))

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java Wed Jan 23 17:33:48 2008
@@ -272,7 +272,7 @@
     /**
      * Initialize a newly-loaded instance.
      */
-    private boolean initializeState(OpenJPAStateManager sm, PCState state,
+    protected boolean initializeState(OpenJPAStateManager sm, PCState state,
         JDBCFetchConfiguration fetch, ConnectionInfo info)
         throws ClassNotFoundException, SQLException {
         Object oid = sm.getObjectId();
@@ -294,7 +294,7 @@
                     Select.SUBS_EXACT);
                 if (res == null && !selectPrimaryKey(sm, mapping, fetch))
                     return false;
-                if (res != null && !res.next())
+                if (isEmptyResult(res))
                     return false;
             } else {
                 ClassMapping[] mappings = mapping.
@@ -311,16 +311,14 @@
                 } else
                     res = getInitializeStateUnionResult(sm, mapping, mappings,
                         fetch);
-                if (res != null && !res.next())
+                if (isEmptyResult(res))
                     return false;
             }
 
             // figure out what type of object this is; the state manager
             // only guarantees to provide a base class
             Class type;
-            if (res == null)
-                type = mapping.getDescribedType();
-            else {
+            if ((type = getType(res, mapping)) == null) {
                 if (res.getBaseMapping() != null)
                     mapping = res.getBaseMapping();
                 res.startDataRequest(mapping.getDiscriminator());
@@ -342,7 +340,7 @@
                 // re-get the mapping in case the instance was a subclass
                 mapping = (ClassMapping) sm.getMetaData();
                 load(mapping, sm, fetch, res);
-                mapping.getVersion().afterLoad(sm, this);
+                getVersion(mapping, sm, res);
             }
             return true;
         } finally {
@@ -350,6 +348,35 @@
                 res.close();
         }
     }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of getting version from the result set.
+     */
+    protected void getVersion(ClassMapping mapping, OpenJPAStateManager sm,
+        Result res) throws SQLException {
+        mapping.getVersion().afterLoad(sm, this);
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of checking whether the result set is empty or not.
+     */
+    protected boolean isEmptyResult(Result res) throws SQLException {
+        if (res != null && !res.next())
+            return true;
+        return false;
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of getting type from the result set.
+     */
+    protected Class getType(Result res, ClassMapping mapping){
+        if (res == null)
+            return mapping.getDescribedType();
+        return null;
+    }
 
     /**
      * Allow the mapping to custom load data. Return null if the mapping
@@ -427,7 +454,7 @@
         sel.wherePrimaryKey(sm.getObjectId(), base, this);
         Result exists = sel.execute(this, fetch);
         try {
-            if (!exists.next())
+            if (isEmptyResult(exists))
                 return false;
 
             // record locked?
@@ -478,7 +505,7 @@
                 sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
                 res = sel.execute(this, jfetch, lockLevel);
                 try {
-                    if (!res.next())
+                 	if (isEmptyResult(res))
                         return false;
                     load(mapping, sm, jfetch, res);
                 } finally {

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java Wed Jan 23 17:33:48 2008
@@ -499,11 +499,11 @@
             for (int i = 0; i < sql.length; i++) {
                 stmnt = null;
                 try {
-                    stmnt = sql[i].prepareStatement(conn);
-                    count += stmnt.executeUpdate();
+                    stmnt = prepareStatement(conn, sql[i]);
+                    count += executeUpdate(conn, stmnt, sql[i], isUpdate);                    
                 } catch (SQLException se) {
                     throw SQLExceptions.getStore(se, sql[i].getSQL(), 
-                    		_store.getDBDictionary());
+                        _store.getDBDictionary());
                 } finally {
                     if (stmnt != null)
                         try { stmnt.close(); } catch (SQLException se) {}
@@ -649,4 +649,22 @@
             sql[i] = ((Select) sels.get(i)).toSelect(false, fetch).getSQL(true);
         return sql;
     }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of executing update.
+     */
+    protected int executeUpdate(Connection conn, PreparedStatement stmnt, 
+        SQLBuffer sqlBuf, boolean isUpdate) throws SQLException {
+        return stmnt.executeUpdate();
+    }
+            
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of preparing statement.
+     */
+    protected PreparedStatement prepareStatement(Connection conn, SQLBuffer sql)
+        throws SQLException {
+        return sql.prepareStatement(conn);
+    }    
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java Wed Jan 23 17:33:48 2008
@@ -132,18 +132,10 @@
         PreparedStatement stmnt = null;
         ResultSet rs = null;
         try {
-            stmnt = sql.prepareStatement(conn);
-            if (timeout >= 0 && dict.supportsQueryTimeout) {
-                if (timeout < 1000) {
-                    timeout = 1000;
-                    if (log.isWarnEnabled())
-                        log.warn(_loc.get("millis-query-timeout"));
-                }
-                stmnt.setQueryTimeout(timeout / 1000);
-            }
-            rs = stmnt.executeQuery();
-            if (!rs.next())
-                throw new LockException(sm.getManagedInstance());
+            stmnt = prepareStatement(conn, sql);
+            setTimeout(stmnt, timeout);
+            rs = executeQuery(conn, stmnt, sql);
+            checkLock(rs, sm);
         } catch (SQLException se) {
             throw SQLExceptions.getStore(se, dict);
         } finally {
@@ -167,5 +159,55 @@
             if (log.isInfoEnabled())
                 log.info(_loc.get("start-trans-for-lock"));
         }
+    }
+    
+    public JDBCStore getStore() {
+        return _store;
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of preparing statement.
+     */
+    protected PreparedStatement prepareStatement(Connection conn, SQLBuffer sql)
+        throws SQLException {
+        return sql.prepareStatement(conn);
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of setting query timeout.
+     */
+    protected void setTimeout(PreparedStatement stmnt, int timeout)
+        throws SQLException {
+        DBDictionary dict = _store.getDBDictionary();
+        if (timeout >= 0 && dict.supportsQueryTimeout) {
+            if (timeout < 1000) {
+                timeout = 1000;
+                if (log.isWarnEnabled())
+                    log.warn(_loc.get("millis-query-timeout"));
+            }
+            stmnt.setQueryTimeout(timeout / 1000);
+        }
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of executing query.
+     */
+    protected ResultSet executeQuery(Connection conn, PreparedStatement stmnt, 
+        SQLBuffer sql) throws SQLException {
+        return stmnt.executeQuery();
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of checking lock from the result set.
+     */
+    protected void checkLock(ResultSet rs, OpenJPAStateManager sm)
+        throws SQLException { 
+        if (!rs.next())
+            throw new LockException(sm.getManagedInstance());
+        return;
     }
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedStatementManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedStatementManagerImpl.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedStatementManagerImpl.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedStatementManagerImpl.java Wed Jan 23 17:33:48 2008
@@ -35,7 +35,6 @@
 import org.apache.openjpa.util.ApplicationIds;
 import org.apache.openjpa.util.OpenJPAException;
 import org.apache.openjpa.util.OptimisticException;
-import org.apache.openjpa.meta.ClassMetaData;
 
 /**
  * Basic prepared statement manager implementation.
@@ -89,12 +88,13 @@
 
         // prepare statement
         String sql = row.getSQL(_dict);
-        PreparedStatement stmnt = _conn.prepareStatement(sql);
-
+        PreparedStatement stmnt = prepareStatement(sql);
+        
         // setup parameters and execute statement
-        row.flush(stmnt, _dict, _store);
+        if (stmnt != null)
+            row.flush(stmnt, _dict, _store);
         try {
-            int count = stmnt.executeUpdate();
+            int count = executeUpdate(stmnt, sql, row);
             if (count != 1) {
                 Object failed = row.getFailedObject();
                 if (failed != null)
@@ -107,7 +107,8 @@
         } catch (SQLException se) {
             throw SQLExceptions.getStore(se, row.getFailedObject(), _dict);
         } finally {
-            try { stmnt.close(); } catch (SQLException se) {}
+            if (stmnt != null)
+               try { stmnt.close(); } catch (SQLException se) {}
         }
 
         // set auto assign values
@@ -128,4 +129,22 @@
 
     public void flush() {
     }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of executing update.
+     */
+    protected int executeUpdate(PreparedStatement stmnt, String sql, 
+        RowImpl row) throws SQLException {
+        return stmnt.executeUpdate();
+    }
+        
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of preparing statement.
+     */
+    protected PreparedStatement prepareStatement(String sql)
+        throws SQLException {
+        return _conn.prepareStatement(sql);
+    }    
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SQLStoreQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SQLStoreQuery.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SQLStoreQuery.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SQLStoreQuery.java Wed Jan 23 17:33:48 2008
@@ -23,6 +23,7 @@
 import java.io.StringReader;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -157,7 +158,7 @@
     /**
      * Executes the filter as a SQL query.
      */
-    private static class SQLExecutor
+    protected static class SQLExecutor
         extends AbstractExecutor {
 
         private final ClassMetaData _meta;
@@ -224,20 +225,14 @@
 
             PreparedStatement stmnt = null;
             try {
-                stmnt = buf.prepareCall(conn);
+                stmnt = prepareCall(conn, buf);
 
                 int index = 0;
-                for (Iterator i = paramList.iterator(); i.hasNext();)
+                for (Iterator i = paramList.iterator(); i.hasNext() && 
+                    stmnt != null;)
                     dict.setUnknown(stmnt, ++index, i.next(), null);
                 
-                int count = 0;
-                if (_call && stmnt.execute() == false) {
-                    count = stmnt.getUpdateCount();
-                }
-                else {
-                    // native insert, update, delete
-                    count = stmnt.executeUpdate();
-                }
+                int count = executeUpdate(store, conn, stmnt, buf);                
                 return Numbers.valueOf(count);
             } catch (SQLException se) {
                 if (stmnt != null)
@@ -276,20 +271,23 @@
             try {
                 // use the right method depending on sel vs. proc, lrs setting
                 if (_select && !range.lrs)
-                    stmnt = buf.prepareStatement(conn);
+                    stmnt = prepareStatement(conn, buf);
                 else if (_select)
-                    stmnt = buf.prepareStatement(conn, fetch, -1, -1);
+                    stmnt = prepareStatement(conn, buf, fetch, -1, -1);
                 else if (!range.lrs)
-                    stmnt = buf.prepareCall(conn);
+                    stmnt = prepareCall(conn, buf);
                 else
-                    stmnt = buf.prepareCall(conn, fetch, -1, -1);
+                    stmnt = prepareCall(conn, buf, fetch, -1, -1);
 
                 int index = 0;
-                for (Iterator i = paramList.iterator(); i.hasNext();)
+                for (Iterator i = paramList.iterator(); i.hasNext() && 
+                    stmnt != null;)
                     dict.setUnknown(stmnt, ++index, i.next(), null);
 
-                ResultSetResult res = new ResultSetResult(conn, stmnt,
-                    stmnt.executeQuery(), store);
+                ResultSet rs = executeQuery(store, conn, stmnt, buf, paramList);
+                ResultSetResult res = stmnt != null ? 
+                    new ResultSetResult(conn, stmnt, rs, store) :
+                    new ResultSetResult(conn, rs, dict);
                 if (_resultMapping != null)
                     rop = new MappedQueryResultObjectProvider(_resultMapping,
                         store, fetch, res);
@@ -318,6 +316,72 @@
 
         public boolean isPacking(StoreQuery q) {
             return q.getContext().getCandidateType() == null;
+        }
+        
+        /**
+         * This method is to provide override for non-JDBC or JDBC-like 
+         * implementation of preparing call statement.
+         */
+        protected PreparedStatement prepareCall(Connection conn, SQLBuffer buf)
+            throws SQLException {
+            return buf.prepareCall(conn);            
+        }
+        
+        /**
+         * This method is to provide override for non-JDBC or JDBC-like 
+         * implementation of executing update.
+         */
+        protected int executeUpdate(JDBCStore store, Connection conn, 
+            PreparedStatement stmnt, SQLBuffer buf) 
+            throws SQLException {
+            int count = 0;
+            if (_call && stmnt.execute() == false) {
+                count = stmnt.getUpdateCount();
+            }
+            else {
+                // native insert, update, delete
+                count = stmnt.executeUpdate();
+            }
+            return count;
+        }
+        
+        /**
+         * This method is to provide override for non-JDBC or JDBC-like 
+         * implementation of preparing call statement.
+         */
+        protected PreparedStatement prepareCall(Connection conn, SQLBuffer buf,
+            JDBCFetchConfiguration fetch, int rsType, int rsConcur)
+            throws SQLException {
+            return buf.prepareCall(conn, fetch, rsType, rsConcur);  
+        }
+
+        /**
+         * This method is to provide override for non-JDBC or JDBC-like 
+         * implementation of preparing statement.
+         */
+        protected PreparedStatement prepareStatement(Connection conn, 
+            SQLBuffer buf) throws SQLException {
+            return buf.prepareStatement(conn);
+        }
+        
+        /**
+         * This method is to provide override for non-JDBC or JDBC-like 
+         * implementation of preparing statement.
+         */
+        protected PreparedStatement prepareStatement(Connection conn, 
+            SQLBuffer buf, JDBCFetchConfiguration fetch, int rsType,
+            int rsConcur) throws SQLException {
+            return buf.prepareStatement(conn, fetch, rsType, rsConcur);
+        }
+        
+        /**
+         * This method is to provide override for non-JDBC or JDBC-like 
+         * implementation of executing query.
+         */
+        protected ResultSet executeQuery(JDBCStore store, Connection conn,
+            PreparedStatement stmnt, SQLBuffer buf, List paramList)
+            throws SQLException {
+            return stmnt.executeQuery();
         }
     }
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java Wed Jan 23 17:33:48 2008
@@ -30,7 +30,6 @@
 import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
 import org.apache.openjpa.jdbc.meta.ClassMapping;
 import org.apache.openjpa.jdbc.schema.Column;
-import org.apache.openjpa.jdbc.schema.Index;
 import org.apache.openjpa.jdbc.schema.PrimaryKey;
 import org.apache.openjpa.jdbc.schema.Schema;
 import org.apache.openjpa.jdbc.schema.SchemaGroup;
@@ -38,6 +37,7 @@
 import org.apache.openjpa.jdbc.schema.Schemas;
 import org.apache.openjpa.jdbc.schema.Table;
 import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.RowImpl;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.SQLExceptions;
 import org.apache.openjpa.lib.conf.Configurable;
@@ -431,8 +431,8 @@
 
         PreparedStatement stmnt = null;
         try {
-            stmnt = insert.prepareStatement(conn);
-            stmnt.executeUpdate();
+            stmnt = prepareStatement(conn, insert);
+            executeUpdate(_conf, conn, stmnt, insert, RowImpl.ACTION_INSERT);
         } finally {
             if (stmnt != null)
                 try { stmnt.close(); } catch (SQLException se) {}
@@ -464,17 +464,16 @@
                 null, false, dict.supportsSelectForUpdate, 0, Long.MAX_VALUE,
                 false, true);
 
-        PreparedStatement stmnt = select.prepareStatement(conn);
+        PreparedStatement stmnt = prepareStatement(conn, select);
         ResultSet rs = null;
         try {
-            rs = stmnt.executeQuery();
-            if (!rs.next())
-                return -1;
-            return dict.getLong(rs, 1);
+            rs = executeQuery(_conf, conn, stmnt, select);
+            return getSequence(rs, dict);
         } finally {
             if (rs != null)
                 try { rs.close(); } catch (SQLException se) {}
-            try { stmnt.close(); } catch (SQLException se) {}
+            if (stmnt != null)    
+                try { stmnt.close(); } catch (SQLException se) {}
         }
     }
 
@@ -522,8 +521,8 @@
                     append(_seqColumn).append(" = ").
                     appendValue(Numbers.valueOf(cur), _seqColumn);
 
-                stmnt = upd.prepareStatement(conn);
-                updates = stmnt.executeUpdate();
+                stmnt = prepareStatement(conn, upd);
+                updates = executeUpdate(_conf, conn, stmnt, upd, RowImpl.ACTION_UPDATE);
             } finally {
                 if (rs != null) 
                     try { rs.close(); } catch (SQLException se) {}
@@ -703,5 +702,42 @@
 
         public long seq = 1L;
         public long max = 0L;
+    }
+
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of preparing statement.
+     */
+    protected PreparedStatement prepareStatement(Connection conn, SQLBuffer buf)
+        throws SQLException {
+        return buf.prepareStatement(conn);
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of executing update.
+     */
+    protected int executeUpdate(JDBCConfiguration conf, Connection conn,  
+        PreparedStatement stmnt, SQLBuffer buf, int opcode) throws SQLException {
+        return stmnt.executeUpdate();
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of executing query.
+     */
+    protected ResultSet executeQuery(JDBCConfiguration conf, Connection conn,
+        PreparedStatement stmnt, SQLBuffer buf) throws SQLException {
+        return stmnt.executeQuery();
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of getting sequence from the result set.
+     */
+    protected long getSequence(ResultSet rs, DBDictionary dict) throws SQLException {
+        if (rs == null || !rs.next())
+            return -1;
+        return dict.getLong(rs, 1);
     }
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java Wed Jan 23 17:33:48 2008
@@ -49,7 +49,7 @@
  *
  * @author Abe White
  */
-class PCPath
+public class PCPath
     extends AbstractVal
     implements JDBCPath {
 
@@ -549,7 +549,7 @@
     /**
      * Expression state.
      */
-    private static class PathExpState
+    public static class PathExpState
         extends ExpState {
 
         public FieldMapping field = null;

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java Wed Jan 23 17:33:48 2008
@@ -93,7 +93,7 @@
     /**
      * Expression state.
      */
-    private static class ParamExpState
+    public static class ParamExpState
         extends ConstExpState {
 
         public Object sqlValue = null;

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java Wed Jan 23 17:33:48 2008
@@ -87,7 +87,6 @@
 import org.apache.openjpa.kernel.Filters;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.kernel.exps.Path;
-import org.apache.openjpa.kernel.exps.Literal;
 import org.apache.openjpa.lib.conf.Configurable;
 import org.apache.openjpa.lib.conf.Configuration;
 import org.apache.openjpa.lib.jdbc.ConnectionDecorator;
@@ -1982,7 +1981,7 @@
             ExpState state = val.initialize(sel, ctx, 0);
             // JDBC Paths are always PCPaths; PCPath implements Val
             ExpState pathState = ((Val) path).initialize(sel, ctx, 0);
-            val.calculateValue(sel, ctx, state, (Val) path, pathState);
+            calculateValue(val, sel, ctx, state, path, pathState);
 
             // append the value with a null for the Select; i
             // indicates that the
@@ -3476,7 +3475,7 @@
         if (str == null)
             return new Sequence[0];
 
-        PreparedStatement stmnt = conn.prepareStatement(str);
+        PreparedStatement stmnt = prepareStatement(conn, str);        
         ResultSet rs = null;
         try {
             int idx = 1;
@@ -3485,21 +3484,19 @@
             if (sequenceName != null)
                 stmnt.setString(idx++, sequenceName);
 
-            rs = stmnt.executeQuery();
-            List seqList = new ArrayList();
-            while (rs.next())
-                seqList.add(newSequence(rs));
-            return (Sequence[]) seqList.toArray(new Sequence[seqList.size()]);
-        } finally {
+            rs = executeQuery(conn, stmnt, str);
+            return getSequence(rs);            
+         } finally {
             if (rs != null)
                 try {
                     rs.close();
                 } catch (SQLException se) {
                 }
-            try {
-                stmnt.close();
-            } catch (SQLException se) {
-            }
+            if (stmnt != null)    
+                try {
+                    stmnt.close();
+                } catch (SQLException se) {
+                }
         }
     }
 
@@ -3880,20 +3877,16 @@
             });
         }
 
-        PreparedStatement stmnt = conn.prepareStatement(query);
+        PreparedStatement stmnt = prepareStatement(conn, query);
         ResultSet rs = null;
         try {
-            rs = stmnt.executeQuery();
-            if (!rs.next())
-                throw new StoreException(_loc.get("no-genkey"));
-            Object key = rs.getObject(1);
-            if (key == null)
-                log.warn(_loc.get("invalid-genkey", col));
-            return key;
+            rs = executeQuery(conn, stmnt, query);
+            return getKey(rs, col);
         } finally {
             if (rs != null)
                 try { rs.close(); } catch (SQLException se) {}
-            try { stmnt.close(); } catch (SQLException se) {} 
+            if (stmnt != null)    
+                try { stmnt.close(); } catch (SQLException se) {} 
         }
     }
 
@@ -4277,4 +4270,55 @@
             OpenJPAStateManager  sm, ClassMapping cmd ) {
         return disableBatch;
     }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of executing query.
+     */
+    protected ResultSet executeQuery(Connection conn, PreparedStatement stmnt, String sql 
+        ) throws SQLException {
+        return stmnt.executeQuery();
+    }
+            
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of preparing statement.
+     */
+    protected PreparedStatement prepareStatement(Connection conn, String sql)
+        throws SQLException {
+        return conn.prepareStatement(sql);
+    }    
+ 
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of getting sequence from the result set.
+     */
+    protected Sequence[] getSequence(ResultSet rs) throws SQLException {
+        List seqList = new ArrayList();
+        while (rs != null && rs.next())
+            seqList.add(newSequence(rs));
+        return (Sequence[]) seqList.toArray(new Sequence[seqList.size()]);
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of getting key from the result set.
+     */
+    protected Object getKey (ResultSet rs, Column col) throws SQLException {
+        if (!rs.next())
+            throw new StoreException(_loc.get("no-genkey"));
+        Object key = rs.getObject(1);
+        if (key == null)
+            log.warn(_loc.get("invalid-genkey", col));
+        return key;        
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of calculating value.
+     */
+    protected void calculateValue(Val val, Select sel, ExpContext ctx, 
+        ExpState state, Path path, ExpState pathState) {
+        val.calculateValue(sel, ctx, state, (Val) path, pathState);
+    }    
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java Wed Jan 23 17:33:48 2008
@@ -92,6 +92,17 @@
     }
 
     /**
+     * Constructor.
+     */
+    public ResultSetResult(Connection conn,
+        ResultSet rs, DBDictionary dict) {
+        _conn = conn;
+        _stmnt = null;
+        _rs = rs;
+        _dict = dict;
+    }
+
+    /**
      * JDBC 2 constructor. Relies on being able to retrieve the statement
      * from the result set, and the connection from the statement.
      */

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowImpl.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowImpl.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowImpl.java Wed Jan 23 17:33:48 2008
@@ -20,7 +20,6 @@
 
 import java.io.InputStream;
 import java.io.Reader;
-import java.lang.reflect.Method;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.sql.Array;
@@ -57,10 +56,10 @@
 public class RowImpl
     implements Row, Cloneable {
 
-    protected static final Object NULL = new Object();
+    public static final Object NULL = new Object();
     protected static final int VALID = 2 << 0;
 
-    private static final int RAW = Integer.MIN_VALUE;
+    public static final int RAW = Integer.MIN_VALUE;
 
     protected byte flags = 0;
     private final Column[] _cols;
@@ -949,5 +948,13 @@
         System.arraycopy(_types, start, row._types, start, len);
         if (isValid())
             row.setValid(true);
+    }
+    
+    public Object[] getVals() {
+        return _vals;
+    }
+    
+    public int[] getTypes() {
+        return _types;
     }
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java Wed Jan 23 17:33:48 2008
@@ -641,4 +641,12 @@
             return sub;
         }
     }
+    
+    public void setParameters(List params) {
+        _params = params;
+    }
+    
+    public List getColumns() {
+        return _cols;
+    }
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java Wed Jan 23 17:33:48 2008
@@ -297,10 +297,11 @@
         try {
             SQLBuffer sql = toSelectCount();
             conn = store.getConnection();
-            stmnt = sql.prepareStatement(conn);
-            rs = stmnt.executeQuery();
-            rs.next();
-            return rs.getInt(1);
+            stmnt = prepareStatement(conn, sql, null, 
+                ResultSet.TYPE_FORWARD_ONLY, 
+                ResultSet.CONCUR_READ_ONLY, false);
+            rs = executeQuery(conn, stmnt, sql, false, store);
+            return getCount(rs);
         } finally {
             if (rs != null)
                 try { rs.close(); } catch (SQLException se) {}
@@ -342,31 +343,21 @@
         }
 
         SQLBuffer sql = toSelect(forUpdate, fetch);
-        int rsType = (isLRS() && supportsRandomAccess(forUpdate))
+        boolean isLRS = isLRS();
+        int rsType = (isLRS && supportsRandomAccess(forUpdate))
             ? -1 : ResultSet.TYPE_FORWARD_ONLY;
         Connection conn = store.getConnection();
         PreparedStatement stmnt = null;
         ResultSet rs = null;
         try {
-            if (isLRS())
-                stmnt = sql.prepareStatement(conn, fetch, rsType, -1);
+            if (isLRS) 
+                stmnt = prepareStatement(conn, sql, fetch, rsType, -1, true); 
             else
-                stmnt = sql.prepareStatement(conn, rsType, -1);
-
-            // if this is a locking select and the lock timeout is greater than
-            // the configured query timeout, use the lock timeout
-            if (forUpdate && _dict.supportsQueryTimeout && fetch != null 
-                && fetch.getLockTimeout() > stmnt.getQueryTimeout() * 1000) {
-                int timeout = fetch.getLockTimeout();
-                if (timeout < 1000) {
-                    timeout = 1000; 
-                    Log log = _conf.getLog(JDBCConfiguration.LOG_JDBC);
-                    if (log.isWarnEnabled())
-                        log.warn(_loc.get("millis-query-timeout"));
-                }
-                stmnt.setQueryTimeout(timeout / 1000);
-            }
-            rs = stmnt.executeQuery();
+                stmnt = prepareStatement(conn, sql, null, rsType, -1, false);
+            
+            setTimeout(stmnt, forUpdate, fetch);
+            
+            rs = executeQuery(conn, stmnt, sql, isLRS, store);
         } catch (SQLException se) {
             // clean up statement
             if (stmnt != null)
@@ -375,17 +366,8 @@
             throw se;
         }
 
-        SelectResult res = new SelectResult(conn, stmnt, rs, _dict);
-        res.setSelect(this);
-        res.setStore(store);
-        res.setLocking(forUpdate);
-        try {
-            addEagerResults(res, this, store, fetch);
-        } catch (SQLException se) {
-            res.close();
-            throw se;
-        }
-        return res;
+        return getEagerResult(conn, stmnt, rs, store, fetch, forUpdate, 
+            sql.getSQL());
     }
 
     /**
@@ -421,6 +403,80 @@
             }
             eager.put(entry.getKey(), eres);
         }
+    }
+
+
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of preparing statement.
+     */
+    protected PreparedStatement prepareStatement(Connection conn, 
+        SQLBuffer sql, JDBCFetchConfiguration fetch, int rsType, 
+        int rsConcur, boolean isLRS) throws SQLException {
+        if (fetch == null)
+            return sql.prepareStatement(conn, rsType, rsConcur);
+        else
+            return sql.prepareStatement(conn, fetch, rsType, -1);
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of setting query timeout.
+     */
+    protected void setTimeout(PreparedStatement stmnt, boolean forUpdate,
+        JDBCFetchConfiguration fetch) throws SQLException {
+        // if this is a locking select and the lock timeout is greater than
+        // the configured query timeout, use the lock timeout
+        if (forUpdate && _dict.supportsQueryTimeout && fetch != null 
+            && fetch.getLockTimeout() > stmnt.getQueryTimeout() * 1000) {
+            int timeout = fetch.getLockTimeout();
+            if (timeout < 1000) {
+                timeout = 1000; 
+                Log log = _conf.getLog(JDBCConfiguration.LOG_JDBC);
+                if (log.isWarnEnabled())
+                    log.warn(_loc.get("millis-query-timeout"));
+            }
+            stmnt.setQueryTimeout(timeout / 1000);
+        }
+    }
+
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of executing query.
+     */
+    protected ResultSet executeQuery(Connection conn, PreparedStatement stmnt, 
+        SQLBuffer sql, boolean isLRS, JDBCStore store) throws SQLException {
+        return stmnt.executeQuery();
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of getting count from the result set.
+     */
+    protected int getCount(ResultSet rs) throws SQLException {
+        rs.next();
+        return rs.getInt(1);
+    }
+    
+    /**
+     * This method is to provide override for non-JDBC or JDBC-like 
+     * implementation of executing eager selects.
+     */
+    protected Result getEagerResult(Connection conn, 
+        PreparedStatement stmnt, ResultSet rs, JDBCStore store, 
+        JDBCFetchConfiguration fetch, boolean forUpdate, String sqlStr) 
+        throws SQLException {
+        SelectResult res = new SelectResult(conn, stmnt, rs, _dict);
+        res.setSelect(this);
+        res.setStore(store);
+        res.setLocking(forUpdate);
+        try {
+            addEagerResults(res, this, store, fetch);
+        } catch (SQLException se) {
+            res.close();
+            throw se;
+        }
+        return res;
     }
 
     /////////////////////////

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Bootstrap.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Bootstrap.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Bootstrap.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Bootstrap.java Wed Jan 23 17:33:48 2008
@@ -39,7 +39,7 @@
  */
 public class Bootstrap {
 
-    private static final Class[] FACTORY_ARGS =
+    protected static final Class[] FACTORY_ARGS =
         new Class[]{ ConfigurationProvider.class };
 
     private static Localizer s_loc = Localizer.forPackage(Bootstrap.class);
@@ -124,7 +124,7 @@
         return (BrokerFactory) meth.invoke(null, new Object[]{ conf });
     }
 
-    private static String getFactoryClassName(ConfigurationProvider conf,
+    protected static String getFactoryClassName(ConfigurationProvider conf,
         ClassLoader loader) {
         try {
             return getFactoryClass(conf, loader).getName();

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java Wed Jan 23 17:33:48 2008
@@ -2420,10 +2420,7 @@
             }
 
             // make sure we don't already have the instance cached
-            StateManagerImpl other = getStateManagerImplById(id, false);
-            if (other != null && !other.isDeleted() && !other.isNew())
-                throw new ObjectExistsException(_loc.get("cache-exists",
-                    obj.getClass().getName(), id)).setFailedObject(obj);
+            checkForDuplicateId(id, obj);
 
             // if had embedded sm, null it
             if (sm != null)
@@ -3817,7 +3814,7 @@
                     _cache.remove(id, sm);
                     break;
                 case STATUS_OID_ASSIGN:
-                    _cache.assignObjectId(id, sm);
+                    assignObjectId(_cache, id, sm);
                     break;
                 case STATUS_COMMIT_NEW:
                     _cache.commitNew(id, sm);
@@ -4699,5 +4696,24 @@
                 }
             };
         }
+    }
+
+    /**
+     * Assign the object id to the cache. Exception will be
+     * thrown if the id already exists in the cache. 
+     */
+    protected void assignObjectId(Object cache, Object id, 
+        StateManagerImpl sm) {
+        ((ManagedCache) cache).assignObjectId(id, sm); 
+    }
+
+    /** 
+     * This method makes sure we don't already have the instance cached
+     */
+    protected void checkForDuplicateId(Object id, Object obj) {
+        StateManagerImpl other = getStateManagerImplById(id, false);
+        if (other != null && !other.isDeleted() && !other.isNew())
+            throw new ObjectExistsException(_loc.get("cache-exists",
+                obj.getClass().getName(), id)).setFailedObject(obj);
     }
 }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java Wed Jan 23 17:33:48 2008
@@ -3001,7 +3001,7 @@
     /**
      * Mark the field as loaded or unloaded.
      */
-    private void setLoaded(int field, boolean isLoaded) {
+    public void setLoaded(int field, boolean isLoaded) {
         // don't continue if loaded state is already correct; otherwise we
         // can end up clearing _fieldImpl when we shouldn't
         if (_loaded.get(field) == isLoaded)

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java?rev=614763&r1=614762&r2=614763&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java Wed Jan 23 17:33:48 2008
@@ -22,8 +22,6 @@
 import java.lang.instrument.IllegalClassFormatException;
 import java.security.ProtectionDomain;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
 import javax.persistence.EntityManager;
 import javax.persistence.spi.ClassTransformer;
 import javax.persistence.spi.PersistenceProvider;
@@ -73,7 +71,7 @@
      */
     public OpenJPAEntityManagerFactory createEntityManagerFactory(String name,
         String resource, Map m) {
-        PersistenceProductDerivation pd = new PersistenceProductDerivation();
+        PersistenceProductDerivation pd = newPersistenceProductDerivation();
         try {
             Object poolValue = Configurations.removeProperty(EMF_POOL, m);
             ConfigurationProvider cp = pd.load(resource, name, m);
@@ -101,7 +99,7 @@
         }
         
         if (poolValue == null || !((Boolean) poolValue).booleanValue())
-            return Bootstrap.newBrokerFactory(cp, loader);
+            return newBrokerFactory(cp, loader);
         else
             return Bootstrap.getBrokerFactory(cp, loader);
     }
@@ -201,4 +199,19 @@
             return _trans.transform(cl, name, previousVersion, pd, bytes);
         }
 	}
+
+    /**
+     * Return a persistence product deviration with default setting.
+     */
+    public PersistenceProductDerivation newPersistenceProductDerivation() {
+        return new PersistenceProductDerivation();
+    }
+
+    /**
+     * Return a broker factory for the given configuration and class loader.
+     */
+    public BrokerFactory newBrokerFactory(ConfigurationProvider cp,
+        ClassLoader loader) {
+        return Bootstrap.newBrokerFactory(cp, loader);
+    }
 }