You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2012/01/24 23:26:28 UTC

svn commit: r1235533 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ openjpa-kernel/src/main/java/org/...

Author: ppoddar
Date: Tue Jan 24 22:26:27 2012
New Revision: 1235533

URL: http://svn.apache.org/viewvc?rev=1235533&view=rev
Log:
OPENJPA-2099: Use thread gate for reused select. Guard parameter binding

Modified:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingQuery.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
    openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestGate.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java Tue Jan 24 22:26:27 2012
@@ -644,6 +644,8 @@ public interface JDBCConfiguration
      * Sets if select statements are aggressively cached.
      * An aggressive select cache assumes that {@link FetchConfiguration fetch plan}
      * does not change between execution.
+     * <br>
+     * This setting can be changed once and only once.
      *  
      * @since 2.2.0
      */

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java Tue Jan 24 22:26:27 2012
@@ -40,6 +40,7 @@ import org.apache.openjpa.jdbc.sql.Selec
 import org.apache.openjpa.jdbc.sql.SelectExecutor;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.ThreadGate;
 import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.meta.ValueStrategies;
 import org.apache.openjpa.util.InternalException;
@@ -50,8 +51,10 @@ import org.apache.openjpa.util.UserExcep
  * Mapping for a single-valued field that delegates to a {@link ValueHandler}.
  *
  * @author Abe White
+ * @author Pinaki Poddar (select cache)
  * @since 0.4.0
  */
+@SuppressWarnings("serial")
 public class HandlerFieldStrategy
     extends AbstractFieldStrategy
     implements Joinable, Embeddable {
@@ -65,7 +68,8 @@ public class HandlerFieldStrategy
     protected Object[] _args = null;
     protected boolean _load = false;
     protected boolean _lob = false;
-    private Select    _select;
+    private Select    _executor;
+    private ThreadGate _lock = new ThreadGate();
     
     public void map(boolean adapt) {
         if (field.getHandler() == null)
@@ -222,28 +226,33 @@ public class HandlerFieldStrategy
             }
         }
         Select sel;
-        if (_select == null) {
-        	sel = store.getSQLFactory().newSelect();
-        	if (store.getConfiguration().getSelectCacheEnabled()) {
-        		_select = sel;
-        	}
-            sel.select(_cols);
-        } else {
-        	sel = _select;
-        }
-        
-        field.wherePrimaryKey(sel, sm, store);
-
-        Result res = sel.execute(store, fetch);
-        Object val = null;
         try {
-            if (res.next())
-                val = HandlerStrategies.loadDataStore(field, res, null, _cols);
+        	_lock.lock();
+	        if (_executor == null) {
+	        	sel = store.getSQLFactory().newSelect();
+	        	if (store.getConfiguration().getSelectCacheEnabled()) {
+	        		_executor = sel;
+	        	}
+	            sel.select(_cols);
+	        } else {
+	        	sel = _executor;
+	        }
+	        
+	        field.wherePrimaryKey(sel, sm, store);
+	
+	        Result res = sel.execute(store, fetch);
+	        Object val = null;
+	        try {
+	            if (res.next())
+	                val = HandlerStrategies.loadDataStore(field, res, null, _cols);
+	        } finally {
+	            res.close();
+	        }
+	
+	        loadEmbedded(sm, store, fetch, val);
         } finally {
-            res.close();
+        	_lock.unlock();
         }
-
-        loadEmbedded(sm, store, fetch, val);
     }
 
     public Object toDataStoreValue(Object val, JDBCStore store) {

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java Tue Jan 24 22:26:27 2012
@@ -58,6 +58,7 @@ import org.apache.openjpa.jdbc.sql.Union
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.lib.log.Log;
 import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.ThreadGate;
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.JavaTypes;
@@ -93,6 +94,7 @@ public class RelationFieldStrategy
     private Boolean _fkOid = null;
     
     private SelectExecutor _executor;
+    private ThreadGate _lock = new ThreadGate();
     
     public void map(boolean adapt) {
         if (field.getTypeCode() != JavaTypes.PC || field.isEmbeddedPC())
@@ -775,56 +777,63 @@ public class RelationFieldStrategy
         // back to our fk table if not an inverse mapping (in which case we
         // can just make sure the inverse cols == our pk values)
         Union union;
-        if (_executor == null) {
-        	union = store.getSQLFactory().newUnion(rels.length);
-            union.setExpectedResultCount(1, false);
-            if (fetch.getSubclassFetchMode(field.getTypeMapping()) != JDBCFetchConfiguration.EAGER_JOIN)
-                    union.abortUnion();
-            if (((JDBCConfiguration)field.getMappingRepository().getConfiguration()).getSelectCacheEnabled()) {
-            	_executor = union;
-            }
-        } else {
-        	union = (Union)_executor;
-        }
-        union.select(new Union.Selector() {
-            public void select(Select sel, int idx) {
-            	ForeignKey fk = field.getForeignKey(rels[idx]);
-            	ClassMapping mapping = field.getDefiningMapping();
-            	Object oid = sm.getObjectId();
-                if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE) {
-                    sel.whereForeignKey(fk, oid, mapping, store);
-                } else {
-                    if (!field.isBidirectionalManyToOneJoinTable()) {
-                    	if (sel.isReadOnly()) {
-                    		resJoins[idx] = sel.getJoins();
-                    	} else {
-                    		resJoins[idx] = sel.newJoins().joinRelation(field.getName(), fk, rels[idx],
-                                subs, false, false);
-                    	}
-                        field.wherePrimaryKey(sel, sm, store);
-                    } else {
-                    	if (sel.isReadOnly()) {
-                    		resJoins[idx] = sel.getJoins();
-                    	} else { 
-                    		resJoins[idx] = sel.newJoins().joinRelation(null, 
-                    				field.getBidirectionalOneToManyJoinForeignKey(), rels[idx],
-                                    subs, false, false);
-                    	}
-                        sel.whereForeignKey(field.getBidirectionalOneToManyElementForeignKey(), oid, mapping, store);
-                    }
-                }
-                if (!sel.isReadOnly()) {
-                	sel.select(rels[idx], subs, store, fetch, JDBCFetchConfiguration.EAGER_JOIN, resJoins[idx]);
-                }
-            }
-        });
-
-        Result res = union.execute(store, fetch);
         try {
-            Object val = (res.next()) ? res.load(rels[res.indexOf()], store, fetch, resJoins[res.indexOf()]) : null;
-            sm.storeObject(field.getIndex(), val);
+        	_lock.lock();
+	        if (_executor == null) {
+	        	union = store.getSQLFactory().newUnion(rels.length);
+	            union.setExpectedResultCount(1, false);
+	            if (fetch.getSubclassFetchMode(field.getTypeMapping()) != JDBCFetchConfiguration.EAGER_JOIN)
+	                    union.abortUnion();
+	            if (((JDBCConfiguration)field.getMappingRepository().getConfiguration()).getSelectCacheEnabled()) {
+	            	_executor = union;
+	            }
+	        } else {
+	        	union = (Union)_executor;
+	        }
+	        union.select(new Union.Selector() {
+	            public void select(Select sel, int idx) {
+	            	ForeignKey fk = field.getForeignKey(rels[idx]);
+	            	ClassMapping mapping = field.getDefiningMapping();
+	            	Object oid = sm.getObjectId();
+	                if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE) {
+	                    sel.whereForeignKey(fk, oid, mapping, store);
+	                } else {
+	                    if (!field.isBidirectionalManyToOneJoinTable()) {
+	                    	if (sel.isReadOnly()) {
+	                    		resJoins[idx] = sel.getJoins();
+	                    	} else {
+	                    		resJoins[idx] = sel.newJoins().joinRelation(field.getName(), fk, rels[idx],
+	                                subs, false, false);
+	                    	}
+	                        field.wherePrimaryKey(sel, sm, store);
+	                    } else {
+	                    	if (sel.isReadOnly()) {
+	                    		resJoins[idx] = sel.getJoins();
+	                    	} else { 
+	                    		resJoins[idx] = sel.newJoins().joinRelation(null, 
+	                    				field.getBidirectionalOneToManyJoinForeignKey(), rels[idx],
+	                                    subs, false, false);
+	                    	}
+	                        sel.whereForeignKey(field.getBidirectionalOneToManyElementForeignKey(), 
+	                        		oid, mapping, store);
+	                    }
+	                }
+	                if (!sel.isReadOnly()) {
+	                	sel.select(rels[idx], subs, store, fetch, 
+	                			JDBCFetchConfiguration.EAGER_JOIN, resJoins[idx]);
+	                }
+	            }
+	        });
+	
+	        Result res = union.execute(store, fetch);
+	        try {
+	        	sm.storeObject(field.getIndex(), res.next()
+	            	? res.load(rels[res.indexOf()], store, fetch, resJoins[res.indexOf()]) : null);
+	        } finally {
+	            res.close();
+	        }
         } finally {
-            res.close();
+        	_lock.unlock();
         }
     }
 

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java Tue Jan 24 22:26:27 2012
@@ -40,10 +40,10 @@ import org.apache.openjpa.jdbc.sql.Joins
 import org.apache.openjpa.jdbc.sql.Result;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.jdbc.sql.SelectExecutor;
-import org.apache.openjpa.jdbc.sql.SelectImpl;
 import org.apache.openjpa.jdbc.sql.Union;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.kernel.StateManagerImpl;
+import org.apache.openjpa.lib.util.ThreadGate;
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.util.ChangeTracker;
@@ -70,6 +70,7 @@ import org.apache.openjpa.util.Proxy;
 public abstract class StoreCollectionFieldStrategy
     extends ContainerFieldStrategy {
 	protected SelectExecutor _executor;
+	protected ThreadGate _lock = new ThreadGate();
 	
     /**
      * Return the foreign key used to join to the owning field for the given
@@ -165,6 +166,7 @@ public abstract class StoreCollectionFie
         else {
             final ClassMapping[] elems = getIndependentElementMappings(true);
             Union union = (Union) sel;
+            if (union.isReadOnly())
             if (fetch.getSubclassFetchMode(field.getElementMapping().
                 getTypeMapping()) != JDBCFetchConfiguration.EAGER_JOIN)
                 union.abortUnion();
@@ -182,6 +184,7 @@ public abstract class StoreCollectionFie
         // we limit further eager fetches to joins, because after this point
         // the select has been modified such that parallel clones may produce
         // invalid sql
+    	if (sel.isReadOnly()) return;
         boolean outer = field.getNullValue() != FieldMapping.NULL_EXCEPTION;
         // force inner join for inner join fetch 
         if (fetch.hasFetchInnerJoin(field.getFullName(false)))
@@ -359,8 +362,7 @@ public abstract class StoreCollectionFie
                 mappedByValue = owner.getPersistenceCapable();
                 res.setMappedByFieldMapping(mappedByFieldMapping);
                 res.setMappedByValue(mappedByValue);
-            } else if (coll instanceof Collection && 
-                ((Collection) coll).size() > 0) {
+            } else if (coll instanceof Collection && !((Collection) coll).isEmpty()) {
                 // Customer (1) <--> Orders(n)
                 // coll contains the values of the toMany field (Orders)
                 // get the StateManager of this toMany value
@@ -525,7 +527,11 @@ public abstract class StoreCollectionFie
             return;
         }
         // select data for this state manager
-        synchronized (this) {
+        // Select can be configured for reuse. The locking mechanics ensures that
+        // under reuse scenario, the Select structure is built under a thread gate
+        // but later usage is unguarded because a reused select is (almost) immutable.
+        try {
+        	_lock.lock();
 	        final ClassMapping[] elems = getIndependentElementMappings(true);
 	        final Joins[] resJoins = new Joins[Math.max(1, elems.length)];
 	        Union union;
@@ -577,6 +583,8 @@ public abstract class StoreCollectionFie
 	        } else {
 	            sm.storeObject(field.getIndex(), coll);
 	        }
+        } finally {
+        	_lock.unlock();
         }
     }
 
@@ -635,6 +643,7 @@ public abstract class StoreCollectionFie
         }
         return oid;
     }
+        
     
     public String toString() {
     	return getClass().getSimpleName() + '[' + field.getName() + ']';

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java Tue Jan 24 22:26:27 2012
@@ -24,13 +24,22 @@ import org.apache.openjpa.jdbc.schema.Co
 /**
  * A binding parameter in a SQL statement.
  * <br>
- * A binding parameter is used in <tt>WHERE<tt> clause. The parameter is identified by an
- * immutable key and has a value. The parameter is further qualified by whether it is
- * user specified (e.g. from a query parameter) or internally generated (e.g. a discriminator
- * value for inheritance join). A database column can also be optionally associated with 
- * a binding parameter.
+ * A binding parameter is used in <tt>WHERE</tt> clause. The parameter is identified by an
+ * immutable key and has a value. The value of a parameter is bound to a thread and hence
+ * different thread may see different value. These parameters are associated with a {@link Select}
+ * and they are the only mutable components of an otherwise {@link SelectExecutor#isReadOnly() immutable}  
+ * select. 
+ * <br><b>NOTE:</b>
+ * The primary assumption of usage is that the binding parameter values to a cached select and
+ * executing it are carried out in the same thread. 
+ * <br> 
+ * The parameter is further qualified by whether it is user specified (e.g. from a query parameter) 
+ * or internally generated (e.g. a discriminator value for inheritance join). A database column can 
+ * also be optionally associated with a binding parameter. Currently {@link SQLBuffer#bind(Object, Column)
+ * rebinding} a parameter to a value is only possible if the parameter is associated with a column.
  * 
  * @see SQLBuffer#appendValue(Object, Column, org.apache.openjpa.kernel.exps.Parameter)
+ * @see SQLBuffer#bind(Object, Column)
  * 
  * @author Pinaki Poddar
  *
@@ -42,7 +51,7 @@ public class BindParameter {
 	private final Column  _column;
 	// key of this parameter
 	private final Object  _key;
-	private Object _value;
+	private ThreadLocal<Object> _value = new ThreadLocal<Object>();
 	
 	/**
 	 * Constructs a parameter with given key, column and user flag.
@@ -58,21 +67,21 @@ public class BindParameter {
 		_key = key;
 		_user = user;
 		_column = column;
-		_value  = value;
+		_value.set(value);
 	}
 	
 	/**
 	 * Gets the value bound to this parameter. Can be null.
 	 */
 	public Object getValue() {
-		return _value;
+		return _value.get();
 	}
 	
 	/**
 	 * Binds the given value to this parameter. Can be null.
 	 */
 	public void setValue(Object value) {
-		_value = value;
+		_value.set(value);
 	}
 
 	/**

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java Tue Jan 24 22:26:27 2012
@@ -112,6 +112,15 @@ public class LogicalUnion
         return false;
     }
 
+	@Override
+	public boolean isReadOnly() {
+		for (int i = 0; i < sels.length; i++) {
+			if (sels[i].isReadOnly())
+				return true;
+		}
+		return false;
+	}
+	
     public void abortUnion() {
     }
 
@@ -235,8 +244,7 @@ public class LogicalUnion
         if (getExpectedResultCount() == 1) {
             AbstractResult res;
             for (int i = 0; i < sels.length; i++) {
-                res = (AbstractResult) sels[i].execute(store, fetch,
-                    lockLevel);
+                res = (AbstractResult) sels[i].execute(store, fetch, lockLevel);
                 res.setBaseMapping(mappings[i]);
                 res.setIndexOf(i);
 
@@ -267,8 +275,7 @@ public class LogicalUnion
         try {
             List l;
             for (int i = 0; i < res.length; i++) {
-                res[i] = (AbstractResult) sels[i].execute(store, fetch,
-                    lockLevel);
+                res[i] = (AbstractResult) sels[i].execute(store, fetch, lockLevel);
                 res[i].setBaseMapping(mappings[i]);
                 res[i].setIndexOf(i);
 
@@ -999,4 +1006,5 @@ public class LogicalUnion
             return a1.length - a2.length;
         }
     }
+
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java Tue Jan 24 22:26:27 2012
@@ -776,17 +776,4 @@ public interface Select
      */
     public DBDictionary getDictionary() ; 
     
-    /**
-     * Affirms if this select is structurally immutable.
-     * A select becomes immutable upon {@link #execute(JDBCStore, JDBCFetchConfiguration) execution}.
-     * There is no explicit way to turn a select into read-only status.
-     * <br>
-     * The immutable contract does not prevent {@link SQLBuffer#bind(Object, Column) binding} 
-     * new values to {@link BindParameter parameters}.  
-     * 
-     * @return false on construction, true after execution.
-     * 
-     * @since 2.2.0
-     */
-    boolean isReadOnly();
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java Tue Jan 24 22:26:27 2012
@@ -23,6 +23,7 @@ import java.sql.SQLException;
 import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
 import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.schema.Column;
 
 /**
  * Interface for configuring and executing a SQL select.
@@ -151,4 +152,19 @@ public interface SelectExecutor {
      * @since 2.0.0
      */
     public boolean hasMultipleSelects();
+    
+    /**
+     * Affirms if this select is structurally immutable.
+     * A select becomes immutable upon {@link #execute(JDBCStore, JDBCFetchConfiguration) execution}.
+     * There is no explicit way to turn a select into read-only status.
+     * <br>
+     * The immutable contract does not prevent {@link SQLBuffer#bind(Object, Column) binding} 
+     * new values to {@link BindParameter parameters}.  
+     * 
+     * @return false on construction, true after execution.
+     * 
+     * @since 2.2.0
+     */
+    boolean isReadOnly();
+
 }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingQuery.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingQuery.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingQuery.java Tue Jan 24 22:26:27 2012
@@ -271,11 +271,14 @@ public class DelegatingQuery
         }
     }
 
-    public void setCandidateType(Class cls, boolean subs) {
+    public void setCandidateType(Class<?> cls, boolean subs) {
         try {
+        	lock();
             _query.setCandidateType(cls, subs);
         } catch (RuntimeException re) {
             throw translate(re);
+        } finally {
+        	unlock();
         }
     }
 
@@ -289,9 +292,12 @@ public class DelegatingQuery
 
     public void setReadOnly(boolean readOnly) {
         try {
+        	lock();
             _query.setReadOnly(readOnly);
         } catch (RuntimeException re) {
             throw translate(re);
+        } finally {
+        	unlock();
         }
     }
 

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java Tue Jan 24 22:26:27 2012
@@ -58,11 +58,11 @@ import org.apache.openjpa.conf.OpenJPACo
 public class ImplHelper {
 
     // Cache for from/to type assignments
-    private static final Map _assignableTypes =
+    private static final Map<Class<?>,Map<?,?>> _assignableTypes =
         new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD);
 
     // map of all new unenhanced instances active in this classloader
-    public static final Map _unenhancedInstanceMap =
+    public static final Map<Object,PersistenceCapable> _unenhancedInstanceMap =
         new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD) {
 
             protected boolean eq(Object x, Object y) {
@@ -91,13 +91,13 @@ public class ImplHelper {
      * @see StoreManager#loadAll
      * @since 0.4.0
      */
-    public static Collection loadAll(Collection sms, StoreManager store,
+    public static Collection<Object> loadAll(Collection<OpenJPAStateManager> sms, StoreManager store,
         PCState state, int load, FetchConfiguration fetch, Object context) {
-        Collection failed = null;
+        Collection<Object> failed = null;
         OpenJPAStateManager sm;
         LockManager lm;
-        for (Iterator itr = sms.iterator(); itr.hasNext();) {
-            sm = (OpenJPAStateManager) itr.next();
+        for (Iterator<OpenJPAStateManager> itr = sms.iterator(); itr.hasNext();) {
+            sm = itr.next();
             if (sm.getManagedInstance() == null) {
                 if (!store.initialize(sm, state, fetch, context))
                     failed = addFailedId(sm, failed);
@@ -110,23 +110,23 @@ public class ImplHelper {
             } else if (!store.exists(sm, context))
                 failed = addFailedId(sm, failed);
         }
-        return (failed == null) ? Collections.EMPTY_LIST : failed;
+        if (failed == null) return Collections.emptyList();
+        return failed;
     }
 
     /**
      * Add identity of given instance to collection.
      */
-    private static Collection addFailedId(OpenJPAStateManager sm,
-        Collection failed) {
+    private static Collection<Object> addFailedId(OpenJPAStateManager sm, Collection<Object> failed) {
         if (failed == null)
-            failed = new ArrayList();
+            failed = new ArrayList<Object>();
         failed.add(sm.getId());
         return failed;
     }
 
     /**
      * Generate a value for the given metadata, or return null. Generates
-     * values for hte following strategies: {@link ValueStrategies#SEQUENCE},
+     * values for the following strategies: {@link ValueStrategies#SEQUENCE},
      * {@link ValueStrategies#UUID_STRING}, {@link ValueStrategies#UUID_HEX}
      */
     public static Object generateIdentityValue(StoreContext ctx,
@@ -136,7 +136,7 @@ public class ImplHelper {
 
     /**
      * Generate a value for the given metadata, or return null. Generates
-     * values for hte following strategies: {@link ValueStrategies#SEQUENCE},
+     * values for the following strategies: {@link ValueStrategies#SEQUENCE},
      * {@link ValueStrategies#UUID_STRING}, {@link ValueStrategies#UUID_HEX}
      */
     public static Object generateFieldValue(StoreContext ctx,
@@ -218,11 +218,9 @@ public class ImplHelper {
      *
      * @since 1.0.0
      */
-    public static boolean isManagedType(OpenJPAConfiguration conf, Class type) {
-        return (PersistenceCapable.class.isAssignableFrom(type)
-            || (type != null
-                && (conf == null || conf.getRuntimeUnenhancedClassesConstant()
-                    == RuntimeUnenhancedClassesModes.SUPPORTED)
+    public static boolean isManagedType(OpenJPAConfiguration conf, Class<?> type) {
+        return (type != null && PersistenceCapable.class.isAssignableFrom(type)
+            || ((conf == null || conf.getRuntimeUnenhancedClassesConstant()== RuntimeUnenhancedClassesModes.SUPPORTED)
                 && PCRegistry.isRegistered(type)));
     }
 
@@ -246,7 +244,7 @@ public class ImplHelper {
      * @param to second class instance to be checked for assignability
      * @return true if the "to" class is assignable to the "from" class
      */
-    public static boolean isAssignable(Class from, Class to) {
+    public static boolean isAssignable(Class<?> from, Class<?> to) {
         if (from == null || to == null)
             return false;
 
@@ -308,8 +306,7 @@ public class ImplHelper {
         }
     }
 
-    public static void registerPersistenceCapable(
-        ReflectingPersistenceCapable pc) {
+    public static void registerPersistenceCapable(ReflectingPersistenceCapable pc) {
         _unenhancedInstanceMap.put(pc.getManagedInstance(), pc);
     }
 

Modified: openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestGate.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestGate.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestGate.java (original)
+++ openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestGate.java Tue Jan 24 22:26:27 2012
@@ -66,7 +66,7 @@ public class TestGate extends TestCase {
 			};
 			futures.add(threadPool.submit(r));
 		}
-		
+		Thread.sleep(THREAD_TIME*10);
 		for (Future<?> f : futures) {
 			try {
 				f.get();

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java Tue Jan 24 22:26:27 2012
@@ -87,22 +87,22 @@ public interface OpenJPAQuery<X> extends
      * Return the candidate collection, or <code>null</code> if an
      * extent was specified instead of a collection.
      */
-    public Collection getCandidateCollection();
+    public Collection<?> getCandidateCollection();
 
     /**
      * Set a collection of candidates.
      */
-    public OpenJPAQuery<X> setCandidateCollection(Collection coll);
+    public OpenJPAQuery<X> setCandidateCollection(Collection<?> coll);
 
     /**
      * Query result element type.
      */
-    public Class getResultClass();
+    public Class<?> getResultClass();
 
     /**
      * Query result element type.
      */
-    public OpenJPAQuery<X> setResultClass(Class type);
+    public OpenJPAQuery<X> setResultClass(Class<?> type);
 
     /**
      * Whether subclasses are included in the query results.
@@ -150,7 +150,7 @@ public interface OpenJPAQuery<X> extends
     /**
      * Set parameters.
      */
-    public OpenJPAQuery<X> setParameters(Map params);
+    public OpenJPAQuery<X> setParameters(Map<?,?> params);
 
     /**
      * Set parameters.
@@ -169,7 +169,7 @@ public interface OpenJPAQuery<X> extends
      *
      * @param params the named parameter map for the query invocation
      */
-    public String[] getDataStoreActions(Map params);
+    public String[] getDataStoreActions(Map<?,?> params);
 
     public OpenJPAQuery<X> setMaxResults(int maxResult);
 
@@ -207,7 +207,7 @@ public interface OpenJPAQuery<X> extends
      * Gets whether the type of user-supplied bind parameter value and the type of target persistent 
      * property they bind to are checked with strong or weak constraint.
      * 
-     * @return the booelan state. False by default, i.e. the type of a bind parameter value is checked
+     * @return the boolean state. False by default, i.e. the type of a bind parameter value is checked
      * strongly against the target property type.  
      */
     public boolean getRelaxBindParameterTypeChecking();

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java Tue Jan 24 22:26:27 2012
@@ -213,14 +213,14 @@ public class QueryImpl<X> extends Abstra
 		return this;
 	}
 
-	public Class getResultClass() {
-		Class res = _query.getResultType();
+	public Class<?> getResultClass() {
+		Class<?> res = _query.getResultType();
 		if (res != null)
 			return res;
 		return _query.getCandidateType();
 	}
 
-	public OpenJPAQuery<X> setResultClass(Class cls) {
+	public OpenJPAQuery<X> setResultClass(Class<?> cls) {
 		_em.assertNotCloseInvoked();
 		if (ImplHelper.isManagedType(_em.getConfiguration(), cls))
 			_query.setCandidateType(cls, true);