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/17 15:04:07 UTC

svn commit: r1232415 [1/2] - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ openjpa-jdbc/src/main/java/org/...

Author: ppoddar
Date: Tue Jan 17 14:04:07 2012
New Revision: 1232415

URL: http://svn.apache.org/viewvc?rev=1232415&view=rev
Log:
OPENJPA:2099: Cacheing select construct with class/field strategy. Adding configuration

Added:
    openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ImmutableBooleanValue.java   (with props)
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/conf/JDBCConfigurationImpl.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/meta/ClassMapping.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMappingInfo.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.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/RelationRelationMapTableFieldStrategy.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationToManyTableFieldStrategy.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/DBDictionary.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/meta/InheritanceComparator.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataInheritanceComparator.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataSerializer.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=1232415&r1=1232414&r2=1232415&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 17 14:04:07 2012
@@ -628,5 +628,25 @@ public interface JDBCConfiguration
      * @param util instance of the identifier utility
      */
     public void setIdentifierUtil(DBIdentifierUtil util);
+    
+    /**
+     * Affirms if select statements are aggressively cached.
+     * An aggressive select cache assumes that {@link FetchConfiguration fetch plan}
+     * does not change between execution.
+     * 
+     * @return false by default.
+     *  
+     * @since 2.2.0
+     */
+    public boolean getSelectCacheEnabled();
+    
+    /**
+     * Sets if select statements are aggressively cached.
+     * An aggressive select cache assumes that {@link FetchConfiguration fetch plan}
+     * does not change between execution.
+     *  
+     * @since 2.2.0
+     */
+    public void setSelectCacheEnabled(boolean enable);
 
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java?rev=1232415&r1=1232414&r2=1232415&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java Tue Jan 17 14:04:07 2012
@@ -43,6 +43,8 @@ import org.apache.openjpa.jdbc.sql.MaxDB
 import org.apache.openjpa.jdbc.sql.SQLFactory;
 import org.apache.openjpa.kernel.BrokerImpl;
 import org.apache.openjpa.kernel.StoreContext;
+import org.apache.openjpa.lib.conf.BooleanValue;
+import org.apache.openjpa.lib.conf.ImmutableBooleanValue;
 import org.apache.openjpa.lib.conf.IntValue;
 import org.apache.openjpa.lib.conf.ObjectValue;
 import org.apache.openjpa.lib.conf.PluginValue;
@@ -87,6 +89,7 @@ public class JDBCConfigurationImpl
     public PluginValue driverDataSourcePlugin;
     public MappingFactoryValue mappingFactoryPlugin;
     public ObjectValue identifierUtilPlugin;
+    public ImmutableBooleanValue cacheSelect;
 
     // used internally
     private String firstUser = null;
@@ -350,6 +353,9 @@ public class JDBCConfigurationImpl
         identifierUtilPlugin.setString(aliases[0]);
         identifierUtilPlugin.setInstantiatingGetter("getIdentifierUtilInstance");
 
+        cacheSelect = new ImmutableBooleanValue("jdbc.CachesSelect");
+        addValue(cacheSelect);
+        cacheSelect.setDefault("false");
         
         // this static initializer is to get past a weird
         // ClassCircularityError that happens only under IBM's
@@ -996,5 +1002,13 @@ public class JDBCConfigurationImpl
     public void setIdentifierUtil(DBIdentifierUtil util) {
         identifierUtilPlugin.set(util);
     }
+    
+    public boolean getSelectCacheEnabled() {
+    	return cacheSelect.get();
+    }
+    public void setSelectCacheEnabled(boolean enable) {
+    	cacheSelect.set(enable);
+    }
+
 
 }

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=1232415&r1=1232414&r2=1232415&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 Tue Jan 17 14:04:07 2012
@@ -260,9 +260,9 @@ public class JDBCStoreManager implements
     private boolean exists(ClassMapping mapping, Object oid, Object context) {
         // add where conditions on base class to avoid joins if subclass
         // doesn't use oid as identifier
-        Select sel = _sql.newSelect();
         while (mapping.getJoinablePCSuperclassMapping() != null)
             mapping = mapping.getJoinablePCSuperclassMapping();
+        Select sel = mapping.getSelect();
 
         sel.wherePrimaryKey(oid, mapping, this);
         if (_log.isTraceEnabled()) {
@@ -301,8 +301,7 @@ public class JDBCStoreManager implements
         FetchConfiguration fetch, Object context) {
         ConnectionInfo info = (ConnectionInfo) context;
         try {
-            return initializeState(sm, state, (JDBCFetchConfiguration) fetch, 
-                info);
+            return initializeState(sm, state, (JDBCFetchConfiguration) fetch, info);
         } catch (ClassNotFoundException cnfe) {
             throw new UserException(cnfe);
         } catch (SQLException se) {
@@ -332,27 +331,24 @@ public class JDBCStoreManager implements
                 Boolean custom = customLoad(sm, mapping, state, fetch);
                 if (custom != null)
                     return custom.booleanValue();
-                res = getInitializeStateResult(sm, mapping, fetch,
-                    Select.SUBS_EXACT);
+                res = getInitializeStateResult(sm, mapping, fetch, Select.SUBS_EXACT);
                 if (res == null && !selectPrimaryKey(sm, mapping, fetch))
                     return false;
                 if (isEmptyResult(res))
                     return false;
             } else {
-                ClassMapping[] mappings = mapping.
-                    getIndependentAssignableMappings();
+                ClassMapping[] mappings = mapping.getIndependentAssignableMappings();
                 if (mappings.length == 1) {
                     mapping = mappings[0];
                     Boolean custom = customLoad(sm, mapping, state, fetch);
                     if (custom != null)
                         return custom.booleanValue();
-                    res = getInitializeStateResult(sm, mapping, fetch,
-                        Select.SUBS_ANY_JOINABLE);
+                    res = getInitializeStateResult(sm, mapping, fetch, Select.SUBS_ANY_JOINABLE);
                     if (res == null && !selectPrimaryKey(sm, mapping, fetch))
                         return false;
-                } else
-                    res = getInitializeStateUnionResult(sm, mapping, mappings,
-                        fetch);
+                } else {
+                    res = getInitializeStateUnionResult(sm, mapping, mappings, fetch);
+                }
                 if (isEmptyResult(res))
                     return false;
             }
@@ -365,8 +361,7 @@ public class JDBCStoreManager implements
                     mapping = res.getBaseMapping();
                 res.startDataRequest(mapping.getDiscriminator());
                 try {
-                    type = mapping.getDiscriminator().getClass(this, mapping,
-                        res);
+                    type = mapping.getDiscriminator().getClass(this, mapping, res);
                 } finally {
                     res.endDataRequest();
                 }
@@ -378,19 +373,15 @@ public class JDBCStoreManager implements
             sm.initialize(type, state);
 
             if (info != null && info.result != null) {
-                FieldMapping mappedByFieldMapping = info.result.
-                    getMappedByFieldMapping();
+                FieldMapping mappedByFieldMapping = info.result.getMappedByFieldMapping();
                 Object mappedByObject = info.result.getMappedByValue();
                 if (mappedByFieldMapping != null && mappedByObject != null)
                     if (mappedByObject instanceof OpenJPAId &&
                         mapping.getExtraFieldDataIndex(mappedByFieldMapping.getIndex()) != -1) {
-                        // The inverse relation can not be set since
-                        // we are eagerly loading this sm for
-                        // a sm owner that is still in the process of 
-                        // initializing itself.
+                        // The inverse relation can not be set since we are eagerly loading this sm for
+                        // an owner that is still in the process of initializing itself.
                         // Remember owner oid by setIntermediate().
-                        // The inverse relation is set later by
-                        // setInverseRelation() when the sm owner is fully
+                        // The inverse relation is set later by setInverseRelation() when the owner is fully
                         // initialized.
                         int index = mappedByFieldMapping.getIndex();
                         if (sm.getLoaded().get(index)) {
@@ -535,7 +526,7 @@ public class JDBCStoreManager implements
         FinderQueryImpl fq = getFinder(mapping, fetch);
         if (fq != null)
             return fq.execute(sm, this, fetch);
-        Select sel = _sql.newSelect();
+        Select sel = mapping.getSelect();
         if (!select(sel, mapping, subs, sm, null, fetch,
             JDBCFetchConfiguration.EAGER_JOIN, true, false))
             return null;
@@ -563,7 +554,7 @@ public class JDBCStoreManager implements
         final int eager = Math.min(fetch.getEagerFetchMode(),
             JDBCFetchConfiguration.EAGER_JOIN);
 
-        Union union = _sql.newUnion(mappings.length);
+        Union union = mapping.getUnion(mappings.length);
         union.setExpectedResultCount(1, false);
         if (fetch.getSubclassFetchMode(mapping) != EagerFetchModes.EAGER_JOIN)
             union.abortUnion();
@@ -592,7 +583,7 @@ public class JDBCStoreManager implements
         while (base.getJoinablePCSuperclassMapping() != null)
             base = base.getJoinablePCSuperclassMapping();
 
-        Select sel = _sql.newSelect();
+        Select sel = mapping.getSelect();
         sel.select(base.getPrimaryKeyColumns());
         sel.wherePrimaryKey(sm.getObjectId(), base, this);
         if (_log.isTraceEnabled()) {
@@ -645,7 +636,7 @@ public class JDBCStoreManager implements
             //### use it... would it be worth it to have a small shell select
             //### object that only creates a real select when actually used?
 
-            Select sel = _sql.newSelect();
+            Select sel = mapping.getSelect();
             if (select(sel, mapping, Select.SUBS_EXACT, sm, fields, jfetch,
                 EagerFetchModes.EAGER_JOIN, true, false)) {
                 sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
@@ -818,7 +809,7 @@ public class JDBCStoreManager implements
                     if (rops[i] != null)
                         continue;
 
-                    Select sel = _sql.newSelect();
+                    Select sel = mapping.getSelect();
                     sel.setLRS(true);
                     if (_log.isTraceEnabled()) {
                         _log.trace("executeExtent: "+mappings[i].getDescribedType());
@@ -839,13 +830,12 @@ public class JDBCStoreManager implements
             }
 
             // perform a union on all independent classes
-            Union union = _sql.newUnion(mappings.length);
+            Union union = mapping.getUnion(mappings.length);
             union.setLRS(true);
             final BitSet[] paged = new BitSet[mappings.length];
             union.select(new Union.Selector() {
                 public void select(Select sel, int idx) {
-                    paged[idx] = selectExtent(sel, mappings[idx], jfetch,
-                        subclasses);
+                    paged[idx] = selectExtent(sel, mappings[idx], jfetch, subclasses);
                 }
             });
 
@@ -1124,6 +1114,8 @@ public class JDBCStoreManager implements
     public boolean select(Select sel, ClassMapping mapping, int subs,
         OpenJPAStateManager sm, BitSet fields, JDBCFetchConfiguration fetch,
         int eager, boolean ident, boolean outer) {
+    	if (sel.isReadOnly())
+    		return true;
         // add class conditions so that they're cloned for any batched selects
         boolean joinedSupers = false;    
         if(needClassCondition(mapping, subs, sm)) {
@@ -1134,8 +1126,7 @@ public class JDBCStoreManager implements
         // and cannot be reused during the actual eager select process,
         // preventing infinite recursion
         eager = Math.min(eager, fetch.getEagerFetchMode());
-        FieldMapping eagerToMany = createEagerSelects(sel, mapping, sm, fields,
-            fetch, eager);
+        FieldMapping eagerToMany = createEagerSelects(sel, mapping, sm, fields, fetch, eager);
 
         // select all base class mappings; do this after batching so that
         // the joins needed by these selects don't get in the WHERE clause
@@ -1145,10 +1136,9 @@ public class JDBCStoreManager implements
 
         // select eager to-many relations last because during load they
         // advance the result set and could exhaust it, so no other mappings
-        // can load afterwords
+        // can load afterwards
         if (eagerToMany != null)
-            eagerToMany.selectEagerJoin(sel, sm, this, 
-                fetch.traverseJDBC(eagerToMany), eager);
+            eagerToMany.selectEagerJoin(sel, sm, this, fetch.traverseJDBC(eagerToMany), eager);
 
         // optionally select subclass mappings
         if (subs == Select.SUBS_JOINABLE || subs == Select.SUBS_ANY_JOINABLE)
@@ -1164,8 +1154,7 @@ public class JDBCStoreManager implements
         return mapping.getDiscriminator().addClassConditions(sel, subs == Select.SUBS_JOINABLE, joins);
     }
     
-    private boolean needClassCondition(ClassMapping mapping, int subs,
-        OpenJPAStateManager sm) {
+    private boolean needClassCondition(ClassMapping mapping, int subs, OpenJPAStateManager sm) {
         boolean retVal = false;
         if(sm == null || sm.getPCState() == PCState.TRANSIENT) {
             if(subs == Select.SUBS_JOINABLE || subs == Select.SUBS_NONE) {

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java?rev=1232415&r1=1232414&r2=1232415&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java Tue Jan 17 14:04:07 2012
@@ -31,6 +31,7 @@ import java.util.concurrent.ConcurrentHa
 
 import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.enhance.Reflection;
+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.meta.strats.NoneClassStrategy;
@@ -44,6 +45,8 @@ import org.apache.openjpa.jdbc.sql.Joins
 import org.apache.openjpa.jdbc.sql.Result;
 import org.apache.openjpa.jdbc.sql.RowManager;
 import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.jdbc.sql.SelectExecutor;
+import org.apache.openjpa.jdbc.sql.Union;
 import org.apache.openjpa.kernel.FetchConfiguration;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.kernel.PCState;
@@ -60,17 +63,22 @@ import org.apache.openjpa.util.OpenJPAId
 
 /**
  * Specialization of metadata for relational databases.
+ * <br>
+ * The mapping may reuse the same {@link SelectExecutor select} if the 
+ * {@link JDBCConfiguration#getSelectCacheEnabled() configuration option}
+ * instructs to do so. 
  *
  * @author Abe White
+ * @author Pinaki Poddar (select caching)
  */
+@SuppressWarnings("serial")
 public class ClassMapping
     extends ClassMetaData
     implements ClassStrategy {
 
     public static final ClassMapping[] EMPTY_MAPPINGS = new ClassMapping[0];
 
-    private static final Localizer _loc = Localizer.forPackage
-        (ClassMapping.class);
+    private static final Localizer _loc = Localizer.forPackage(ClassMapping.class);
 
     private final ClassMappingInfo _info;
     private final Discriminator _discrim;
@@ -88,6 +96,9 @@ public class ClassMapping
 
     // maps columns to joinables
     private final Map _joinables = new ConcurrentHashMap();
+    
+    private Select _select;
+    private Union  _union;
 
     /**
      * Constructor. Supply described type and owning repository.
@@ -1109,4 +1120,48 @@ public class ClassMapping
             return true;
         return false;
     }
+    
+    /**
+     * Gets the {@link Select select} used for selecting instances of this mapping.
+     * If {@link JDBCConfiguration#getSelectCacheEnabled() aggressive caching} of
+     * select statements is enabled, then a select is generated for the first call,
+     * cached in this mapping and subsequently returned. A cached select becomes 
+     * {@link Select#isReadOnly() immutable} i.e. no structural modification is
+     * allowed <em>after</em> its corresponding SQL has been executed on the database.
+     * 
+     * @return a new or cached select to select instances of this mapping.  
+     */
+    public Select getSelect() {
+    	Select result = _select;
+    	if (result == null) {
+    		JDBCConfiguration conf = (JDBCConfiguration)getMappingRepository().getConfiguration();
+    		result = conf.getSQLFactoryInstance().newSelect();
+    		if (conf.getSelectCacheEnabled()) {
+    			_select = result;
+    		}
+    	}
+    	return result;
+    }
+    
+    /**
+     * Gets the {@link Union union} used for selecting instances of this mapping.
+     * If {@link JDBCConfiguration#getSelectCacheEnabled() aggressive caching} of
+     * union statements is enabled, then a union is generated for the first call,
+     * cached in this mapping and subsequently returned. A cached union becomes 
+     * {@link Select#isReadOnly() immutable} i.e. no structural modification is
+     * allowed <em>after</em> its corresponding SQL has been executed on the database.
+     * 
+     * @return a new or cached union to select instances of this mapping.  
+     */
+    public Union getUnion(int selects) {
+    	Union result = _union;
+    	if (result == null) {
+    		JDBCConfiguration conf = (JDBCConfiguration)getMappingRepository().getConfiguration();
+    		result = conf.getSQLFactoryInstance().newUnion(selects);
+    		if (conf.getSelectCacheEnabled()) {
+    			_union = result;
+    		}
+    	}
+    	return result;
+    }
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java?rev=1232415&r1=1232414&r2=1232415&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java Tue Jan 17 14:04:07 2012
@@ -81,19 +81,19 @@ public class FieldMapping
     private boolean _outer = false;
     private int _fetchMode = Integer.MAX_VALUE;
     private Unique[] _joinTableUniques; // Unique constraints on JoinTable
-    private Boolean _bidirectionalJoinTableOwner = null;
-    private Boolean _bidirectionalJoinTableNonOwner = null;
+    private Boolean _bidirectionalJoinTableOwner;
+    private Boolean _bidirectionalJoinTableNonOwner;
     
-    private Boolean _bi_MTo1_JT = null;
-    private Boolean _uni_1ToM_FK = null;
-    private Boolean _uni_MTo1_JT = null;
-    private Boolean _uni_1To1_JT = null;
-    private Boolean _bi_1To1_JT = null;
+    private Boolean _bidirectionalManyToOneJoinTable;
+    private Boolean _unidirectionalOneToManyForeignKey;
+    private Boolean _unidirectionalManyToOneJoinTable;
+    private Boolean _unidirectionalOneToOneJoinTable;
+    private Boolean _bidirectionalOneToOneJoinTable;
     
-    private FieldMapping _bi_1ToM_JT_Field = null;
-    private FieldMapping _bi_MTo1_JT_Field = null;
-    private ForeignKey _bi_1ToM_Join_FK = null;
-    private ForeignKey _bi_1ToM_Elem_FK = null;
+    private FieldMapping _bidirectionalOneToManyJoinTableField;
+    private FieldMapping _bidirectionalManyToOneJoinTableField;
+    private ForeignKey _bidirectionalOneToManyJoinForeignKey;
+    private ForeignKey _bidirectionalOneToManyElementForeignKey;
     
     private boolean _hasMapsIdCols = false;
         
@@ -1271,85 +1271,90 @@ public class FieldMapping
         return _bidirectionalJoinTableNonOwner.booleanValue();
     }
     
-    public boolean isBiMTo1JT() {
-        if (_bi_MTo1_JT == null) {
-            _bi_MTo1_JT = getMappingRepository().isBiMTo1JT(this);
+    public boolean isBidirectionalManyToOneJoinTable() {
+        if (_bidirectionalManyToOneJoinTable == null) {
+            _bidirectionalManyToOneJoinTable = getMappingRepository().isBidirectionalManyToOneJoinTable(this);
         }
-        return _bi_MTo1_JT;
+        return _bidirectionalManyToOneJoinTable;
     }
 
-    public boolean isUni1ToMFK() {
-        if (_uni_1ToM_FK == null)
-            _uni_1ToM_FK = getMappingRepository().isUni1ToMFK(this);
-        return _uni_1ToM_FK;
+    public boolean isUnidirectionalOneToManyForeignKey() {
+        if (_unidirectionalOneToManyForeignKey == null)
+            _unidirectionalOneToManyForeignKey = getMappingRepository().isUnidirectionalOneToManyForeignKey(this);
+        return _unidirectionalOneToManyForeignKey;
     }
     
-    public boolean isUniMTo1JT() {
-        if (_uni_MTo1_JT == null)
-            _uni_MTo1_JT = getMappingRepository().isUniMTo1JT(this);
-        return _uni_MTo1_JT;
-    }
-
-    public boolean isUni1To1JT() {
-        if (_uni_1To1_JT == null)
-            _uni_1To1_JT = getMappingRepository().isUni1To1JT(this);
-        return _uni_1To1_JT;
-    }
-
-    public boolean isBi1To1JT() {
-        if (_bi_1To1_JT == null)
-            _bi_1To1_JT = getMappingRepository().isBi1To1JT(this);
-        return _bi_1To1_JT;
+    public boolean isUnidirectionalManyToOneJoinTable() {
+        if (_unidirectionalManyToOneJoinTable == null)
+            _unidirectionalManyToOneJoinTable = getMappingRepository().isUnidirectionalManyToOneJoinTable(this);
+        return _unidirectionalManyToOneJoinTable;
+    }
+
+    public boolean isUnidirectionalOneToOneJoinTable() {
+        if (_unidirectionalOneToOneJoinTable == null)
+            _unidirectionalOneToOneJoinTable = getMappingRepository().isUnidirectionalOneToOneJoinTable(this);
+        return _unidirectionalOneToOneJoinTable;
+    }
+
+    public boolean isBidirectionalOneToOneJoinTable() {
+        if (_bidirectionalOneToOneJoinTable == null)
+            _bidirectionalOneToOneJoinTable = getMappingRepository().isBidirectionalOneToOneJoinTable(this);
+        return _bidirectionalOneToOneJoinTable;
     }
     
-    public FieldMapping getBi_1ToM_JTField() {
-        if (_bi_1ToM_JT_Field == null) {
-            _bi_1ToM_JT_Field = getMappingRepository().getBi_1ToM_JoinTableField(this);
+    public FieldMapping getBidirectionalOneToManyJoinTableField() {
+        if (_bidirectionalOneToManyJoinTableField == null) {
+            _bidirectionalOneToManyJoinTableField = 
+            	getMappingRepository().getBidirectionalOneToManyJoinTableField(this);
         }
-        return _bi_1ToM_JT_Field;
+        return _bidirectionalOneToManyJoinTableField;
     }
     
-    public FieldMapping getBi_MTo1_JTField() {
-        if (_bi_MTo1_JT_Field == null) {
-            _bi_MTo1_JT_Field = getMappingRepository().getBi_MTo1_JoinTableField(this);
+    public FieldMapping getBidirectionalManyToOneJoinTableField() {
+        if (_bidirectionalManyToOneJoinTableField == null) {
+            _bidirectionalManyToOneJoinTableField = 
+            	getMappingRepository().getBidirectionalManyToOneJoinTableField(this);
         }
-        return _bi_MTo1_JT_Field;
+        return _bidirectionalManyToOneJoinTableField;
     }
 
-    public ForeignKey getBi1ToMJoinFK() {
-        if (_bi_1ToM_Join_FK == null) {
-            getBi_1ToM_JTField();
-            if (_bi_1ToM_JT_Field != null)
-                _bi_1ToM_Join_FK = _bi_1ToM_JT_Field.getJoinForeignKey();
+    public ForeignKey getBidirectionalOneToManyJoinForeignKey() {
+        if (_bidirectionalOneToManyJoinForeignKey == null) {
+            getBidirectionalOneToManyJoinTableField();
+            if (_bidirectionalOneToManyJoinTableField != null)
+                _bidirectionalOneToManyJoinForeignKey = _bidirectionalOneToManyJoinTableField.getJoinForeignKey();
         }
-        return _bi_1ToM_Join_FK;
+        return _bidirectionalOneToManyJoinForeignKey;
     }
     
-    public ForeignKey getBi1ToMElemFK() {
-        if (_bi_1ToM_Elem_FK == null) {
-            getBi_1ToM_JTField();
-            if (_bi_1ToM_JT_Field != null)
-                _bi_1ToM_Elem_FK = _bi_1ToM_JT_Field.getElementMapping().getForeignKey();
+    public ForeignKey getBidirectionalOneToManyElementForeignKey() {
+        if (_bidirectionalOneToManyElementForeignKey == null) {
+            getBidirectionalOneToManyJoinTableField();
+            if (_bidirectionalOneToManyJoinTableField != null)
+                _bidirectionalOneToManyElementForeignKey = 
+                	_bidirectionalOneToManyJoinTableField.getElementMapping().getForeignKey();
         }
-        return _bi_1ToM_Elem_FK;
+        return _bidirectionalOneToManyElementForeignKey;
     }
     
-    public void setBi1MJoinTableInfo() {
+    public void setBidirectionalOneToManyJoinTableInfo() {
         if (getAssociationType() == FieldMetaData.ONE_TO_MANY) {
-            FieldMapping mapped = getBi_MTo1_JTField();
+            FieldMapping mapped = getBidirectionalManyToOneJoinTableField();
             if (mapped != null) {
                 FieldMappingInfo info = getMappingInfo();
                 FieldMappingInfo mappedInfo = mapped.getMappingInfo();
                 info.setTableIdentifier(mappedInfo.getTableIdentifier());
                 info.setColumns(mapped.getElementMapping().getValueInfo().getColumns());
-                getElementMapping().getValueInfo().setColumns(
-                    mappedInfo.getColumns());
+                getElementMapping().getValueInfo().setColumns(mappedInfo.getColumns());
             }
         }
     }
    
     public boolean isNonDefaultMappingUsingJoinTableStrategy() {
-        return isBi1To1JT() || isUni1To1JT() || isUniMTo1JT() || isBiMTo1JT();
+        return isBidirectionalOneToOneJoinTable() 
+            || isUnidirectionalOneToOneJoinTable() 
+            || isUnidirectionalManyToOneJoinTable() 
+            || isBidirectionalManyToOneJoinTable();
     }
     
     public void setMapsIdCols(boolean hasMapsIdCols) {

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMappingInfo.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMappingInfo.java?rev=1232415&r1=1232414&r2=1232415&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMappingInfo.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMappingInfo.java Tue Jan 17 14:04:07 2012
@@ -165,7 +165,7 @@ public class FieldMappingInfo
 
     public ForeignKey getJoinForeignKey (final FieldMapping field, Table table,
         boolean adapt) {
-        if (field.isUni1ToMFK()) {
+        if (field.isUnidirectionalOneToManyForeignKey()) {
             List<Column> cols = field.getElementMapping().getValueInfo().getColumns();
             return getJoin(field, table, adapt, cols);
         }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java?rev=1232415&r1=1232414&r2=1232415&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java Tue Jan 17 14:04:07 2012
@@ -105,15 +105,14 @@ import org.apache.openjpa.util.UserExcep
  *
  * @author Abe White
  */
+@SuppressWarnings("serial")
 public class MappingRepository extends MetaDataRepository {
 
-    private static final Localizer _loc = Localizer.forPackage
-        (MappingRepository.class);
+    private static final Localizer _loc = Localizer.forPackage(MappingRepository.class);
 
     private transient DBDictionary _dict = null;
     private transient MappingDefaults _defaults = null;
     
-    // object->queryresultmapping
     private Map<Object, QueryResultMapping> _results = new HashMap<Object, QueryResultMapping>(); 
     private SchemaGroup _schema = null;
     private StrategyInstaller _installer = null;
@@ -260,12 +259,10 @@ public class MappingRepository extends M
     public QueryResultMapping[] getQueryResultMappings() {
         if (_locking) {
             synchronized (this) {
-                Collection values = _results.values();
-                return (QueryResultMapping[]) values.toArray(new QueryResultMapping[values.size()]);
+                return _results.values().toArray(new QueryResultMapping[_results.size()]);
             }
         } else {
-            Collection values = _results.values();
-            return (QueryResultMapping[]) values.toArray(new QueryResultMapping[values.size()]);
+            return _results.values().toArray(new QueryResultMapping[_results.size()]);
         }
     }
 
@@ -273,7 +270,7 @@ public class MappingRepository extends M
      * Return the cached query result mapping with the given name, or null if
      * none.
      */
-    public QueryResultMapping getCachedQueryResultMapping(Class cls, String name) {
+    public QueryResultMapping getCachedQueryResultMapping(Class<?> cls, String name) {
         if (_locking) {
             synchronized (this) {
                 return (QueryResultMapping) _results.get(getQueryResultKey(cls, name));
@@ -286,7 +283,7 @@ public class MappingRepository extends M
     /**
      * Add a query result mapping.
      */
-    public QueryResultMapping addQueryResultMapping(Class cls, String name) {
+    public QueryResultMapping addQueryResultMapping(Class<?> cls, String name) {
         if (_locking) {
             synchronized (this) {
                 return addQueryResultMappingInternal(cls, name);
@@ -296,7 +293,7 @@ public class MappingRepository extends M
         }
     }
 
-    private QueryResultMapping addQueryResultMappingInternal(Class cls, String name) {
+    private QueryResultMapping addQueryResultMappingInternal(Class<?> cls, String name) {
         QueryResultMapping res = new QueryResultMapping(name, this);
         res.setDefiningType(cls);
         _results.put(getQueryResultKey(res), res);
@@ -319,7 +316,7 @@ public class MappingRepository extends M
     /**
      * Remove a query result mapping.
      */
-    public boolean removeQueryResultMapping(Class cls, String name) {
+    public boolean removeQueryResultMapping(Class<?> cls, String name) {
         if (_locking) {
             synchronized (this) {
                 if (name == null)
@@ -1008,8 +1005,7 @@ public class MappingRepository extends M
     protected FieldStrategy handlerCollectionStrategy(FieldMapping field, 
         ValueHandler ehandler, boolean installHandlers) {
         // TODO: JPA 2.0 should ignore this flag and not to serialize
-        if (getConfiguration().getCompatibilityInstance()
-            .getStoreMapCollectionInEntityAsBlob())
+        if (getConfiguration().getCompatibilityInstance().getStoreMapCollectionInEntityAsBlob())
             return null;
         if (installHandlers)
             field.getElementMapping().setHandler(ehandler);
@@ -1024,8 +1020,7 @@ public class MappingRepository extends M
         ValueHandler khandler, ValueHandler vhandler, boolean krel, 
         boolean vrel,  boolean installHandlers) {
         // TODO: JPA 2.0 should ignore this flag and not to serialize
-        if (getConfiguration().getCompatibilityInstance()
-            .getStoreMapCollectionInEntityAsBlob())
+        if (getConfiguration().getCompatibilityInstance().getStoreMapCollectionInEntityAsBlob())
             return null;
         if (installHandlers) {
             field.getKeyMapping().setHandler(khandler);
@@ -1048,14 +1043,13 @@ public class MappingRepository extends M
         FieldMapping mapped = field.getMappedByMapping();
         if (mapped != null) {
             //bi-/M-1/JoinTable ==> join table strategy
-            if (isBiMTo1JT(field)) 
+            if (isBidirectionalManyToOneJoinTable(field)) 
                 return false;
             if (mapped.getTypeCode() == JavaTypes.PC || mapped.getTypeCode() == JavaTypes.PC_UNTYPED)
                 return true;
             if (mapped.getElement().getTypeCode() == JavaTypes.PC)
                 return false;
-            throw new MetaDataException(_loc.get("bad-mapped-by", field,
-                mapped));
+            throw new MetaDataException(_loc.get("bad-mapped-by", field, mapped));
         }
 
         // without a mapped-by, we have to look for clues as to the mapping.
@@ -1064,82 +1058,84 @@ public class MappingRepository extends M
         // an association table
         FieldMappingInfo info = field.getMappingInfo();
         ValueMapping elem = field.getElementMapping();
-        boolean useInverseKeyMapping = DBIdentifier.isNull(info.getTableIdentifier()) && info.getColumns().isEmpty()
-            && !elem.getValueInfo().getColumns().isEmpty();
+        boolean useInverseKeyMapping = DBIdentifier.isNull(info.getTableIdentifier()) 
+                                    && info.getColumns().isEmpty()
+                                    && !elem.getValueInfo().getColumns().isEmpty();
         
         // JPA 2.0: non-default mapping: uni-/1-M/JoinColumn ==> foreign key strategy
-        if (isUni1ToMFK(field)) {
+        if (isUnidirectionalOneToManyForeignKey(field)) {
             return true;
         }
         return useInverseKeyMapping;
     }
         
     public boolean isNonDefaultMappingAllowed() {
-        OpenJPAConfiguration conf = getConfiguration();
-        return getMetaDataFactory().getDefaults().isNonDefaultMappingAllowed(conf);
+        return getMetaDataFactory().getDefaults().isNonDefaultMappingAllowed(getConfiguration());
     }
     
-    public boolean isUniMTo1JT(FieldMapping field) {
-        if (isNonDefaultMappingAllowed() && 
-            field.getAssociationType() == FieldMetaData.MANY_TO_ONE &&
-            hasJoinTable(field) && 
-            !isBidirectional(field))  {
+    public boolean isUnidirectionalManyToOneJoinTable(FieldMapping field) {
+        if (isNonDefaultMappingAllowed() 
+         && field.getAssociationType() == FieldMetaData.MANY_TO_ONE 
+         && hasJoinTable(field) 
+         && !isBidirectional(field))  {
             field.getValueMapping().getValueInfo().setColumns(field.getElementMapping().getValueInfo().getColumns());
             return true;
         }
         return false;
     }
 
-    public boolean isUni1To1JT(FieldMapping field) {
-        if (isNonDefaultMappingAllowed() && 
-            field.getAssociationType() == FieldMetaData.ONE_TO_ONE && 
-            hasJoinTable(field) && 
-            !isBidirectional(field)) {
+    public boolean isUnidirectionalOneToOneJoinTable(FieldMapping field) {
+        if (isNonDefaultMappingAllowed() 
+         && field.getAssociationType() == FieldMetaData.ONE_TO_ONE 
+         && hasJoinTable(field) 
+         && !isBidirectional(field)) {
             field.getValueMapping().getValueInfo().setColumns(field.getElementMapping().getValueInfo().getColumns());
             return true;
         }
         return false;
     }
 
-    public boolean isBi1To1JT(FieldMapping field) {
-        if (isNonDefaultMappingAllowed() && 
-            field.getAssociationType() == FieldMetaData.ONE_TO_ONE && 
-            hasJoinTable(field) && 
-            isBidirectional(field)) {
+    public boolean isBidirectionalOneToOneJoinTable(FieldMapping field) {
+        if (isNonDefaultMappingAllowed() 
+         && field.getAssociationType() == FieldMetaData.ONE_TO_ONE 
+         && hasJoinTable(field) 
+         && isBidirectional(field)) {
             field.getValueMapping().getValueInfo().setColumns(field.getElementMapping().getValueInfo().getColumns());
             return true;
         }
         return false;
     }
     
-    public boolean isUni1ToMFK(FieldMapping field) {
-        if (isNonDefaultMappingAllowed() && 
-            field.getAssociationType() == FieldMetaData.ONE_TO_MANY &&
-            hasJoinColumn(field) &&
-            !isBidirectional(field)) {
+    public boolean isUnidirectionalOneToManyForeignKey(FieldMapping field) {
+        if (isNonDefaultMappingAllowed() 
+         && field.getAssociationType() == FieldMetaData.ONE_TO_MANY 
+         && hasJoinColumn(field) 
+         && !isBidirectional(field)) {
             field.getElementMapping().getValueInfo().setColumns(field.getValueInfo().getColumns());
             return true;
         }
         return false;
     }
     
-    public boolean isBiMTo1JT(FieldMapping field) {
+    public boolean isBidirectionalManyToOneJoinTable(FieldMapping field) {
         FieldMapping mapped = field.getMappedByMapping();
         if (isNonDefaultMappingAllowed()) {
             if (field.getAssociationType() == FieldMetaData.ONE_TO_MANY ) {
                 if (mapped != null && hasJoinTable(mapped))
                     return true;
             } else if (field.getAssociationType() == FieldMetaData.MANY_TO_ONE) {
-                if (getBi_1ToM_JoinTableField(field) != null)
+                if (getBidirectionalOneToManyJoinTableField(field) != null)
                     return true;
             }
         }
         return false;
     }
 
-    // return the inverse field of bidirectional many to one
-    // relation using join table strategy
-    public FieldMapping getBi_1ToM_JoinTableField(FieldMapping field) {
+    /**
+     * Gets the inverse field of bidirectional many to one relation using join table strategy
+     * for the given field.
+     */
+    public FieldMapping getBidirectionalOneToManyJoinTableField(FieldMapping field) {
         if (isNonDefaultMappingAllowed()) {
             if (field.getAssociationType() == FieldMetaData.ONE_TO_MANY) {
                 FieldMapping mappedBy = field.getMappedByMapping();
@@ -1159,9 +1155,10 @@ public class MappingRepository extends M
         return null;
     }
 
-    // return the owning field of bidirectional one to many
-    // relation using join table strategy
-    public FieldMapping getBi_MTo1_JoinTableField(FieldMapping field) {
+    /**
+     * Gets the owning field of bidirectional one to many relation using join table strategy of the given field.
+     */
+    public FieldMapping getBidirectionalManyToOneJoinTableField(FieldMapping field) {
         if (isNonDefaultMappingAllowed()) {
             if (field.getAssociationType() == FieldMetaData.MANY_TO_ONE) {
                 if (!hasJoinTable(field))

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java?rev=1232415&r1=1232414&r2=1232415&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java Tue Jan 17 14:04:07 2012
@@ -87,7 +87,7 @@ public class HandlerRelationMapTableFiel
         union.select(new Union.Selector() {
             public void select(Select sel, int idx) {
                 sel.select(_kcols);
-                if (field.isUni1ToMFK()) {
+                if (field.isUnidirectionalOneToManyForeignKey()) {
                     sel.whereForeignKey(field.getElementMapping().getForeignKey(),
                         sm.getObjectId(), field.getElementMapping().getDeclaredTypeMapping(), store);
                     sel.select(vals[idx], field.getElementMapping().
@@ -146,10 +146,11 @@ public class HandlerRelationMapTableFiel
             throw new MetaDataException(_loc.get("not-relation", val));
         
         FieldMapping mapped = field.getMappedByMapping();
-        if (field.isUni1ToMFK() || (!field.isBiMTo1JT() && mapped != null)) { 
+        if (field.isUnidirectionalOneToManyForeignKey() 
+        || (!field.isBidirectionalManyToOneJoinTable() && mapped != null)) { 
             // map to the owner table
             handleMappedByForeignKey(adapt);
-        } else if (field.isBiMTo1JT() || mapped == null) { 
+        } else if (field.isBidirectionalManyToOneJoinTable() || mapped == null) { 
             // map to a separate table
             field.mapJoin(adapt, true);
             if (val.getTypeMapping().isMapped()) {
@@ -186,11 +187,11 @@ public class HandlerRelationMapTableFiel
         if (map == null || map.isEmpty())
             return;
         
-        if (!field.isBiMTo1JT() && field.getMappedBy() != null)
+        if (!field.isBidirectionalManyToOneJoinTable() && field.getMappedBy() != null)
             return;
 
         Row row = null;
-        if (!field.isUni1ToMFK()) {
+        if (!field.isUnidirectionalOneToManyForeignKey()) {
             row = rm.getSecondaryRow(field.getTable(), Row.ACTION_INSERT);
             row.setForeignKey(field.getJoinForeignKey(), field.getJoinColumnIO(),
                 sm);
@@ -204,7 +205,7 @@ public class HandlerRelationMapTableFiel
             entry = (Map.Entry) itr.next();
             valsm = RelationStrategies.getStateManager(entry.getValue(),
                 ctx);
-            if (field.isUni1ToMFK()){
+            if (field.isUnidirectionalOneToManyForeignKey()){
                 row = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
                     Row.ACTION_UPDATE, valsm, true);
                 row.wherePrimaryKey(valsm);
@@ -223,7 +224,7 @@ public class HandlerRelationMapTableFiel
             // from the view point of the owned side
             PersistenceCapable obj = sm.getPersistenceCapable();
             if (!populateKey(row, valsm, obj, ctx, rm, store)) {
-                if (!field.isUni1ToMFK())
+                if (!field.isUnidirectionalOneToManyForeignKey())
                     rm.flushSecondaryRow(row);
             }
         }
@@ -238,7 +239,7 @@ public class HandlerRelationMapTableFiel
 
     public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
         throws SQLException {
-        if (field.getMappedBy() != null && !field.isBiMTo1JT())
+        if (field.getMappedBy() != null && !field.isBidirectionalManyToOneJoinTable())
             return;
 
         Map map = (Map) sm.fetchObject(field.getIndex());
@@ -269,7 +270,7 @@ public class HandlerRelationMapTableFiel
         Object mkey;
         if (canChange && !change.isEmpty()) {
             Row changeRow = null;
-            if (!field.isUni1ToMFK()) {
+            if (!field.isUnidirectionalOneToManyForeignKey()) {
                 changeRow = rm.getSecondaryRow(field.getTable(),
                     Row.ACTION_UPDATE);
                 changeRow.whereForeignKey(field.getJoinForeignKey(), sm);
@@ -278,7 +279,7 @@ public class HandlerRelationMapTableFiel
             for (Iterator itr = change.iterator(); itr.hasNext();) {
                 mkey = itr.next();
                 valsm = RelationStrategies.getStateManager(map.get(mkey), ctx);
-                if (field.isUni1ToMFK()){
+                if (field.isUnidirectionalOneToManyForeignKey()){
                     changeRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
                         Row.ACTION_UPDATE, valsm, true);
                     changeRow.wherePrimaryKey(valsm);
@@ -288,7 +289,7 @@ public class HandlerRelationMapTableFiel
                 }
                 
                 HandlerStrategies.where(key, mkey, store, changeRow, _kcols);
-                if (!field.isUni1ToMFK())
+                if (!field.isUnidirectionalOneToManyForeignKey())
                     rm.flushSecondaryRow(changeRow);
             }
         }
@@ -297,14 +298,14 @@ public class HandlerRelationMapTableFiel
         Collection rem = ct.getRemoved();
         if (!rem.isEmpty() || (!canChange && !change.isEmpty())) {
             Row delRow = null;
-            if (!field.isUni1ToMFK()) {
+            if (!field.isUnidirectionalOneToManyForeignKey()) {
                 delRow = rm.getSecondaryRow(field.getTable(),
                     Row.ACTION_DELETE);
                 delRow.whereForeignKey(field.getJoinForeignKey(), sm);
             }
             for (Iterator itr = rem.iterator(); itr.hasNext();) {
                 mkey = itr.next();
-                if (field.isUni1ToMFK()){
+                if (field.isUnidirectionalOneToManyForeignKey()){
                     updateSetNull(sm, mkey, store, rm);
                 } else {
                     HandlerStrategies.where(key, mkey, store, delRow, _kcols);
@@ -314,7 +315,7 @@ public class HandlerRelationMapTableFiel
             if (!canChange && !change.isEmpty()) {
                 for (Iterator itr = change.iterator(); itr.hasNext();) {
                     mkey = itr.next();
-                    if (field.isUni1ToMFK()){
+                    if (field.isUnidirectionalOneToManyForeignKey()){
                         updateSetNull(sm, mkey, store, rm);
                     } else { 
                         HandlerStrategies.where(key, itr.next(), store, delRow,  _kcols);
@@ -328,7 +329,7 @@ public class HandlerRelationMapTableFiel
         Collection add = ct.getAdded();
         if (!add.isEmpty() || (!canChange && !change.isEmpty())) {
             Row addRow = null;
-            if (!field.isUni1ToMFK()) {
+            if (!field.isUnidirectionalOneToManyForeignKey()) {
                 addRow = rm.getSecondaryRow(field.getTable(),
                         Row.ACTION_INSERT);
                 addRow.setForeignKey(field.getJoinForeignKey(),
@@ -337,7 +338,7 @@ public class HandlerRelationMapTableFiel
             for (Iterator itr = add.iterator(); itr.hasNext();) {
                 mkey = itr.next();
                 valsm = RelationStrategies.getStateManager(map.get(mkey), ctx);
-                if (field.isUni1ToMFK()){
+                if (field.isUnidirectionalOneToManyForeignKey()){
                     addRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
                         Row.ACTION_UPDATE, valsm, true);
                     addRow.wherePrimaryKey(valsm);
@@ -348,14 +349,14 @@ public class HandlerRelationMapTableFiel
                 
                 HandlerStrategies.set(key, mkey, store, addRow, _kcols,
                     _kio, true);
-                if (!field.isUni1ToMFK())
+                if (!field.isUnidirectionalOneToManyForeignKey())
                     rm.flushSecondaryRow(addRow);
             }
             if (!canChange && !change.isEmpty()) {
                 for (Iterator itr = change.iterator(); itr.hasNext();) {
                     mkey = itr.next();
                     valsm = RelationStrategies.getStateManager(map.get(mkey), ctx);
-                    if (field.isUni1ToMFK()){
+                    if (field.isUnidirectionalOneToManyForeignKey()){
                         addRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
                             Row.ACTION_UPDATE, valsm, true);
                         addRow.wherePrimaryKey(valsm);
@@ -366,7 +367,7 @@ public class HandlerRelationMapTableFiel
                     
                     HandlerStrategies.set(key, mkey, store, addRow, _kcols,
                         _kio, true);
-                    if (!field.isUni1ToMFK())
+                    if (!field.isUnidirectionalOneToManyForeignKey())
                         rm.flushSecondaryRow(addRow);
                 }
             }
@@ -413,9 +414,9 @@ public class HandlerRelationMapTableFiel
     
     public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
         throws SQLException {
-        if ((field.getMappedBy() != null && !field.isBiMTo1JT()))
+        if ((field.getMappedBy() != null && !field.isBidirectionalManyToOneJoinTable()))
             return;
-        if (field.isUni1ToMFK()) {
+        if (field.isUnidirectionalOneToManyForeignKey()) {
             Map mapObj = (Map)sm.fetchObject(field.getIndex());
             updateSetNull(sm, store, rm, mapObj.keySet());
             return;

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java?rev=1232415&r1=1232414&r2=1232415&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java Tue Jan 17 14:04:07 2012
@@ -112,10 +112,10 @@ public abstract class MapTableFieldStrat
             throw new MetaDataException(_loc.get("mapped-by-key", field));
 
         // Non-default mapping Uni-/OneToMany/ForeignKey allows schema components
-        if (field.isUni1ToMFK())  
+        if (field.isUnidirectionalOneToManyForeignKey())  
             return;
-        if (field.isBiMTo1JT())
-            field.setBi1MJoinTableInfo();
+        if (field.isBidirectionalManyToOneJoinTable())
+            field.setBidirectionalOneToManyJoinTableInfo();
         field.getValueInfo().assertNoSchemaComponents(field, !adapt);
     }
     

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=1232415&r1=1232414&r2=1232415&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 17 14:04:07 2012
@@ -28,6 +28,7 @@ import java.util.Set;
 
 import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.enhance.ReflectingPersistenceCapable;
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
 import org.apache.openjpa.jdbc.identifier.DBIdentifier;
 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
 import org.apache.openjpa.jdbc.kernel.JDBCStore;
@@ -37,7 +38,6 @@ import org.apache.openjpa.jdbc.meta.Fiel
 import org.apache.openjpa.jdbc.meta.FieldStrategy;
 import org.apache.openjpa.jdbc.meta.Joinable;
 import org.apache.openjpa.jdbc.meta.MappingInfo;
-import org.apache.openjpa.jdbc.meta.ValueHandler;
 import org.apache.openjpa.jdbc.meta.ValueMapping;
 import org.apache.openjpa.jdbc.meta.ValueMappingImpl;
 import org.apache.openjpa.jdbc.meta.ValueMappingInfo;
@@ -55,13 +55,13 @@ import org.apache.openjpa.jdbc.sql.SQLBu
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.jdbc.sql.SelectExecutor;
 import org.apache.openjpa.jdbc.sql.Union;
-import org.apache.openjpa.kernel.LockManager;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.lib.log.Log;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.meta.MetaDataModes;
 import org.apache.openjpa.util.ApplicationIds;
 import org.apache.openjpa.util.ImplHelper;
 import org.apache.openjpa.util.InternalException;
@@ -74,27 +74,33 @@ import org.apache.openjpa.util.Unsupport
 /**
  * Mapping for a single-valued relation to another entity.
  *
+ * <br>
+ * The strategy may reuse the same {@link SelectExecutor select} if the 
+ * {@link JDBCConfiguration#getSelectCacheEnabled() configuration option}
+ * instructs to do so. 
+
  * @author Abe White
+ * @author Pinaki Poddar (select caching)
  * @since 0.4.0
  */
+@SuppressWarnings("serial")
 public class RelationFieldStrategy
     extends AbstractFieldStrategy
     implements Joinable, Embeddable {
 
-    private static final Localizer _loc = Localizer.forPackage
-        (RelationFieldStrategy.class);
+    private static final Localizer _loc = Localizer.forPackage(RelationFieldStrategy.class);
 
     private Boolean _fkOid = null;
     
+    private SelectExecutor _executor;
+    
     public void map(boolean adapt) {
         if (field.getTypeCode() != JavaTypes.PC || field.isEmbeddedPC())
             throw new MetaDataException(_loc.get("not-relation", field));
 
-        field.getKeyMapping().getValueInfo().assertNoSchemaComponents
-            (field.getKey(), !adapt);
+        field.getKeyMapping().getValueInfo().assertNoSchemaComponents(field.getKey(), !adapt);
         if (!field.isNonDefaultMappingUsingJoinTableStrategy())
-            field.getElementMapping().getValueInfo().assertNoSchemaComponents
-                (field.getElement(), !adapt);
+            field.getElementMapping().getValueInfo().assertNoSchemaComponents(field.getElement(), !adapt);
         boolean criteria = field.getValueInfo().getUseClassCriteria();
 
         // check for named inverse
@@ -102,40 +108,33 @@ public class RelationFieldStrategy
         if (mapped != null) {
             field.getMappingInfo().assertNoSchemaComponents(field, !adapt);
             field.getValueInfo().assertNoSchemaComponents(field, !adapt);
-            mapped.resolve(mapped.MODE_META | mapped.MODE_MAPPING);
+            mapped.resolve(MetaDataModes.MODE_META | MetaDataModes.MODE_MAPPING);
 
             if (!mapped.isMapped() || mapped.isSerialized())
-                throw new MetaDataException(_loc.get("mapped-by-unmapped",
-                    field, mapped));
+                throw new MetaDataException(_loc.get("mapped-by-unmapped", field, mapped));
 
             if (mapped.getTypeCode() == JavaTypes.PC) {
-                if (mapped.getJoinDirection() == mapped.JOIN_FORWARD) {
-                    field.setJoinDirection(field.JOIN_INVERSE);
-                    field.setColumns(mapped.getDefiningMapping().
-                        getPrimaryKeyColumns());
+                if (mapped.getJoinDirection() == FieldMapping.JOIN_FORWARD) {
+                    field.setJoinDirection(FieldMapping.JOIN_INVERSE);
+                    field.setColumns(mapped.getDefiningMapping().getPrimaryKeyColumns());
                 } else if (isTypeUnjoinedSubclass(mapped))
                     throw new MetaDataException(_loc.get
-                        ("mapped-inverse-unjoined", field.getName(),
-                            field.getDefiningMapping(), mapped));
+                        ("mapped-inverse-unjoined", field.getName(), field.getDefiningMapping(), mapped));
 
-                field.setForeignKey(mapped.getForeignKey
-                    (field.getDefiningMapping()));
+                field.setForeignKey(mapped.getForeignKey(field.getDefiningMapping()));
             } else if (mapped.getElement().getTypeCode() == JavaTypes.PC) {
                 if (isTypeUnjoinedSubclass(mapped.getElementMapping()))
                     throw new MetaDataException(_loc.get
-                        ("mapped-inverse-unjoined", field.getName(),
-                            field.getDefiningMapping(), mapped));
+                        ("mapped-inverse-unjoined", field.getName(), field.getDefiningMapping(), mapped));
 
                 // warn the user about making the collection side the owner
                 Log log = field.getRepository().getLog();
                 if (log.isInfoEnabled())
                     log.info(_loc.get("coll-owner", field, mapped));
-                field.setForeignKey(mapped.getElementMapping().
-                    getForeignKey());
-            } else
-                throw new MetaDataException(_loc.get("not-inv-relation",
-                    field, mapped));
-
+                field.setForeignKey(mapped.getElementMapping().getForeignKey());
+            } else {
+                throw new MetaDataException(_loc.get("not-inv-relation", field, mapped));
+            }
             field.setUseClassCriteria(criteria);
             return;
         } 
@@ -157,24 +156,22 @@ public class RelationFieldStrategy
             field.getMappingInfo().setColumns(null);
         }
         
-        if (!field.isBiMTo1JT())
+        if (!field.isBidirectionalManyToOneJoinTable())
             field.mapJoin(adapt, false);
         if (field.getTypeMapping().isMapped()) {
             if (field.getMappedByIdValue() != null) 
                 setMappedByIdColumns();            
              
-            if (!field.isBiMTo1JT()) {
-                ForeignKey fk = vinfo.getTypeJoin(field, field.getName(), true,
-                    adapt);
+            if (!field.isBidirectionalManyToOneJoinTable()) {
+                ForeignKey fk = vinfo.getTypeJoin(field, field.getName(), true, adapt);
                 field.setForeignKey(fk);
             }
             field.setColumnIO(vinfo.getColumnIO());
-            if (vinfo.getJoinDirection() == vinfo.JOIN_INVERSE)
-                field.setJoinDirection(field.JOIN_INVERSE);
-        } else
-            RelationStrategies.mapRelationToUnmappedPC(field, field.getName(),
-                adapt);
-
+            if (vinfo.getJoinDirection() == MappingInfo.JOIN_INVERSE)
+                field.setJoinDirection(FieldMapping.JOIN_INVERSE);
+        } else {
+            RelationStrategies.mapRelationToUnmappedPC(field, field.getName(), adapt);
+        }
         field.setUseClassCriteria(criteria);
         field.mapPrimaryKey(adapt);
         PrimaryKey pk = field.getTable().getPrimaryKey();
@@ -209,11 +206,10 @@ public class RelationFieldStrategy
         }
     }
 
-    private List getMappedByIdColumns(FieldMapping pk) {
-        ClassMetaData embeddedId = ((ValueMappingImpl)pk.getValue()).
-            getEmbeddedMetaData();
+    private List<Column> getMappedByIdColumns(FieldMapping pk) {
+        ClassMetaData embeddedId = ((ValueMappingImpl)pk.getValue()).getEmbeddedMetaData();
         Column[] pkCols = null;
-        List cols = new ArrayList();
+        List<Column> cols = new ArrayList<Column>();
         String mappedByIdValue = field.getMappedByIdValue();
         if (embeddedId != null) {
             FieldMetaData[] fmds = embeddedId.getFields();
@@ -221,20 +217,19 @@ public class RelationFieldStrategy
                 if ((fmds[i].getName().equals(mappedByIdValue)) ||
                     mappedByIdValue.length() == 0) {
                     if (fmds[i].getValue().getEmbeddedMetaData() != null) {
-                        EmbedValueHandler.getEmbeddedIdCols(
-                                (FieldMapping)fmds[i], cols);
-                    } else 
-                        EmbedValueHandler.getIdColumns(
-                                (FieldMapping)fmds[i], cols);
+                        EmbedValueHandler.getEmbeddedIdCols((FieldMapping)fmds[i], cols);
+                    } else {
+                        EmbedValueHandler.getIdColumns((FieldMapping)fmds[i], cols);
+                    }
                 }
             }
             return cols;
         } else { // primary key is single-value
-            Class pkType = pk.getDeclaredType();
+            Class<?> pkType = pk.getDeclaredType();
             FieldMetaData[] pks = field.getValue().getDeclaredTypeMetaData().
                     getPrimaryKeyFields();
             if (pks.length != 1 || pks[0].getDeclaredType() != pkType)
-                return Collections.EMPTY_LIST;
+                return Collections.emptyList();
             pkCols = pk.getColumns();
             for (int i = 0; i < pkCols.length; i++)
                 cols.add(pkCols[i]);
@@ -271,11 +266,11 @@ public class RelationFieldStrategy
 
         OpenJPAStateManager rel = RelationStrategies.getStateManager
             (sm.fetchObjectField(field.getIndex()), store.getContext());
-        if (field.getJoinDirection() == field.JOIN_INVERSE)
+        if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE)
             updateInverse(sm, rel, store, rm);
         else {
             Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT);
-            if (row != null && !field.isBiMTo1JT()) {
+            if (row != null && !field.isBidirectionalManyToOneJoinTable()) {
                 field.setForeignKey(row, rel);
                 // this is for bi-directional maps, the key and value of the 
                 // map are stored in the table of the mapped-by entity  
@@ -295,7 +290,7 @@ public class RelationFieldStrategy
         if (mapField == null)
             return;
         
-        Map mapObj = (Map)rel.fetchObjectField(mapField.getIndex());
+        Map<Object,Object> mapObj = (Map<Object,Object>)rel.fetchObjectField(mapField.getIndex());
         Object keyObj = getMapKeyObj(mapObj, sm.getPersistenceCapable());
         ValueMapping key = mapField.getKeyMapping();
         if (!key.isEmbedded()) {
@@ -311,14 +306,11 @@ public class RelationFieldStrategy
         } else {
             // key is an embeddable or basic type
             FieldStrategy strategy = mapField.getStrategy(); 
-            if (strategy instanceof  
-                    HandlerRelationMapTableFieldStrategy) {
-                HandlerRelationMapTableFieldStrategy strat = 
-                    (HandlerRelationMapTableFieldStrategy) strategy;
+            if (strategy instanceof HandlerRelationMapTableFieldStrategy) {
+                HandlerRelationMapTableFieldStrategy strat = (HandlerRelationMapTableFieldStrategy) strategy;
                 Column[] kcols = strat.getKeyColumns((ClassMapping)meta);
                 ColumnIO kio = strat.getKeyColumnIO();
-                HandlerStrategies.set(key, keyObj, store, row, kcols,
-                        kio, true);
+                HandlerStrategies.set(key, keyObj, store, row, kcols, kio, true);
             }
         } 
     }
@@ -327,19 +319,18 @@ public class RelationFieldStrategy
         FieldMapping[] fields = ((ClassMapping)meta).getFieldMappings();
         for (int i = 0; i < fields.length; i++) {
             FieldMetaData mappedBy = fields[i].getMappedByMetaData();
-            if (fields[i].getDeclaredTypeCode() == JavaTypes.MAP &&
-                mappedBy == field)  
+            if (fields[i].getDeclaredTypeCode() == JavaTypes.MAP && mappedBy == field)  
                 return fields[i];
         } 
         return null;    
     }
     
-    private Object getMapKeyObj(Map mapObj, Object value) {
+    private Object getMapKeyObj(Map<Object,Object> mapObj, Object value) {
         if (value instanceof ReflectingPersistenceCapable)
             value = ((ReflectingPersistenceCapable)value).getManagedInstance(); 
 
-        Set<Map.Entry> entries = mapObj.entrySet();
-        for (Map.Entry entry : entries) {
+        Set<Map.Entry<Object,Object>> entries = mapObj.entrySet();
+        for (Map.Entry<Object,Object> entry : entries) {
             if (entry.getValue() == value)
                 return entry.getKey();
         }
@@ -355,7 +346,7 @@ public class RelationFieldStrategy
         OpenJPAStateManager rel = RelationStrategies.getStateManager
             (sm.fetchObjectField(field.getIndex()), store.getContext());
 
-        if (field.getJoinDirection() == field.JOIN_INVERSE) {
+        if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE) {
             nullInverse(sm, rm);
             updateInverse(sm, rel, store, rm);
         } else {
@@ -363,22 +354,22 @@ public class RelationFieldStrategy
                     field.isBidirectionalJoinTableMappingNonOwner()) ?
                     Row.ACTION_DELETE : Row.ACTION_UPDATE;
             Row row = field.getRow(sm, store, rm, action);
-            if (row != null && !field.isBiMTo1JT()) {
+            if (row != null && !field.isBidirectionalManyToOneJoinTable()) {
                 field.setForeignKey(row, rel);
                 // this is for bi-directional maps, the key and value of the 
                 // map are stored in the table of the mapped-by entity  
                 setMapKey(sm, rel, store, row);
             }
             
-            if (field.isBiMTo1JT()) { // also need to update the join table
+            if (field.isBidirectionalManyToOneJoinTable()) { // also need to update the join table
                 PersistenceCapable invPC = (PersistenceCapable)sm.fetchObject(
-                    field.getBi_1ToM_JTField().getIndex());
+                    field.getBidirectionalOneToManyJoinTableField().getIndex());
                 Row secondaryRow = null;
                 if (invPC != null) {
-                    secondaryRow = rm.getSecondaryRow(field.getBi1ToMJoinFK().getTable(),
+                    secondaryRow = rm.getSecondaryRow(field.getBidirectionalOneToManyJoinForeignKey().getTable(),
                         Row.ACTION_INSERT);
-                    secondaryRow.setForeignKey(field.getBi1ToMElemFK(), null, sm);
-                    secondaryRow.setForeignKey(field.getBi1ToMJoinFK(), null, 
+                    secondaryRow.setForeignKey(field.getBidirectionalOneToManyElementForeignKey(), null, sm);
+                    secondaryRow.setForeignKey(field.getBidirectionalOneToManyJoinForeignKey(), null, 
                         RelationStrategies.getStateManager(invPC,
                         store.getContext()));
                     rm.flushSecondaryRow(secondaryRow);
@@ -392,7 +383,7 @@ public class RelationFieldStrategy
         if (field.getMappedBy() != null)
             return;
 
-        if (field.getJoinDirection() == field.JOIN_INVERSE) {
+        if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE) {
             if (sm.getLoaded().get(field.getIndex())) {
                 OpenJPAStateManager rel = RelationStrategies.getStateManager(sm.
                     fetchObjectField(field.getIndex()), store.getContext());
@@ -504,7 +495,7 @@ public class RelationFieldStrategy
     public int supportsSelect(Select sel, int type, OpenJPAStateManager sm,
         JDBCStore store, JDBCFetchConfiguration fetch) {
         if (type == Select.TYPE_JOINLESS)
-            return (field.getJoinDirection() != field.JOIN_INVERSE
+            return (field.getJoinDirection() != FieldMapping.JOIN_INVERSE
                 && sel.isSelected(field.getTable())) ? 1 : 0;
         if (type == Select.TYPE_TWO_PART)
             return 1;
@@ -535,17 +526,15 @@ public class RelationFieldStrategy
         final OpenJPAStateManager sm, final JDBCStore store,
         final JDBCFetchConfiguration fetch, final int eagerMode) {
         final ClassMapping[] clss = field.getIndependentTypeMappings();
-        if (!(sel instanceof Union))
+        if (!(sel instanceof Union)) {
             selectEagerParallel((Select) sel, clss[0], store, fetch, eagerMode);
-        else {
+        } else {
             Union union = (Union) sel;
-            if (fetch.getSubclassFetchMode (field.getTypeMapping()) 
-                != JDBCFetchConfiguration.EAGER_JOIN)
+            if (fetch.getSubclassFetchMode (field.getTypeMapping()) != JDBCFetchConfiguration.EAGER_JOIN)
                 union.abortUnion();
             union.select(new Union.Selector() {
                 public void select(Select sel, int idx) {
-                    selectEagerParallel(sel, clss[idx], store, fetch,
-                        eagerMode);
+                    selectEagerParallel(sel, clss[idx], store, fetch, eagerMode);
                 }
             });
         }
@@ -556,7 +545,7 @@ public class RelationFieldStrategy
      */
     private void selectEagerParallel(Select sel, ClassMapping cls,
         JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) {
-        if (field.isBiMTo1JT())
+        if (field.isBidirectionalManyToOneJoinTable())
             return;
         sel.selectPrimaryKey(field.getDefiningMapping());
         // set a variable name that does not conflict with any in the query;
@@ -571,7 +560,7 @@ public class RelationFieldStrategy
 
     public void selectEagerJoin(Select sel, OpenJPAStateManager sm,
         JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) {
-        if (field.isBiMTo1JT()) 
+        if (field.isBidirectionalManyToOneJoinTable()) 
             return;
 
         // limit the eager mode to single on recursive eager fetching b/c
@@ -590,7 +579,7 @@ public class RelationFieldStrategy
      * Add the joins needed to select/load eager data.
      */
     private Joins eagerJoin(Joins joins, ClassMapping cls, boolean forceInner) {
-        boolean inverse = field.getJoinDirection() == field.JOIN_INVERSE;
+        boolean inverse = field.getJoinDirection() == FieldMapping.JOIN_INVERSE;
         if (!inverse) {
             joins = join(joins, false);
             joins = setEmbeddedVariable(joins);
@@ -618,7 +607,7 @@ public class RelationFieldStrategy
 
     public int select(Select sel, OpenJPAStateManager sm, JDBCStore store,
         JDBCFetchConfiguration fetch, int eagerMode) {
-        if (field.getJoinDirection() == field.JOIN_INVERSE)
+        if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE)
             return -1;
         // already cached oid?
         if (sm != null && sm.getIntermediate(field.getIndex()) != null)
@@ -633,11 +622,11 @@ public class RelationFieldStrategy
         JDBCFetchConfiguration fetch, Object res)
         throws SQLException {
         // process batched results if we haven't already
-        Map rels;
+        Map<Object,Object> rels;
         if (res instanceof Result)
             rels = processEagerParallelResult(sm, store, fetch, (Result) res);
         else
-            rels = (Map) res;
+            rels = (Map<Object,Object>) res;
 
         // store object for this oid in instance
         sm.storeObject(field.getIndex(), rels.remove(sm.getObjectId()));
@@ -647,7 +636,7 @@ public class RelationFieldStrategy
     /**
      * Process the given batched result.
      */
-    private Map processEagerParallelResult(OpenJPAStateManager sm,
+    private Map<Object,Object> processEagerParallelResult(OpenJPAStateManager sm,
         JDBCStore store, JDBCFetchConfiguration fetch, Result res)
         throws SQLException {
         // do same joins as for load
@@ -657,7 +646,7 @@ public class RelationFieldStrategy
         Joins joins = res.newJoins().setVariable("*");
         eagerJoin(joins, clss[0], true);
 
-        Map rels = new HashMap();
+        Map<Object,Object> rels = new HashMap<Object,Object>();
         ClassMapping owner = field.getDefiningMapping();
         ClassMapping cls;
         Object oid;
@@ -676,7 +665,7 @@ public class RelationFieldStrategy
     public void loadEagerJoin(OpenJPAStateManager sm, JDBCStore store,
         JDBCFetchConfiguration fetch, Result res)
         throws SQLException {
-        if (field.isBiMTo1JT())
+        if (field.isBidirectionalManyToOneJoinTable())
             return;
         ClassMapping cls = field.getIndependentTypeMappings()[0];
 
@@ -719,7 +708,7 @@ public class RelationFieldStrategy
     public void load(OpenJPAStateManager sm, JDBCStore store,
         JDBCFetchConfiguration fetch, Result res)
         throws SQLException {
-        if (field.getJoinDirection() == field.JOIN_INVERSE)
+        if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE)
             return;
         // cached oid?
         if (sm != null && sm.getIntermediate(field.getIndex()) != null)
@@ -732,7 +721,7 @@ public class RelationFieldStrategy
         // get the related object's oid
         ClassMapping relMapping = field.getTypeMapping();
         Object oid = null;
-        if (relMapping.isMapped() && !field.isBiMTo1JT()) { 
+        if (relMapping.isMapped() && !field.isBidirectionalManyToOneJoinTable()) { 
             oid = relMapping.getObjectId(store, res, field.getForeignKey(),
                     field.getPolymorphic() != ValueMapping.POLY_FALSE, null);
         } else {
@@ -746,8 +735,7 @@ public class RelationFieldStrategy
                 if (cols.length == 1) {
                     Object val = res.getObject(cols[0], null, null);
                     if (val != null)
-                        oid = ApplicationIds.fromPKValues(new Object[]{ val },
-                            relMapping);
+                        oid = ApplicationIds.fromPKValues(new Object[]{ val }, relMapping);
                 } else {
                     Object[] vals = new Object[cols.length];
                     for (int i = 0; i < cols.length; i++) {
@@ -767,8 +755,7 @@ public class RelationFieldStrategy
             sm.setIntermediate(field.getIndex(), oid);
     }
 
-    public void load(final OpenJPAStateManager sm, final JDBCStore store,
-        final JDBCFetchConfiguration fetch)
+    public void load(final OpenJPAStateManager sm, final JDBCStore store, final JDBCFetchConfiguration fetch)
         throws SQLException {
         // check for cached oid value, or load oid if no way to join
         if (Boolean.TRUE.equals(_fkOid)) {
@@ -787,41 +774,54 @@ public class RelationFieldStrategy
         // select related mapping columns; joining from the related type
         // 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 = store.getSQLFactory().newUnion(rels.length);
-        union.setExpectedResultCount(1, false);
-        if (fetch.getSubclassFetchMode(field.getTypeMapping())
-            != JDBCFetchConfiguration.EAGER_JOIN)
-            union.abortUnion();
+        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) {
-                if (field.getJoinDirection() == field.JOIN_INVERSE)
-                    sel.whereForeignKey(field.getForeignKey(rels[idx]),
-                        sm.getObjectId(), field.getDefiningMapping(), store);
-                else {
-                    if (!field.isBiMTo1JT()) {
-                        resJoins[idx] = sel.newJoins().joinRelation(field.getName(),
-                            field.getForeignKey(rels[idx]), rels[idx],
-                            field.getSelectSubclasses(), false, false);
+            	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 {
-                        resJoins[idx] = sel.newJoins().joinRelation(null,
-                            field.getBi1ToMJoinFK(), rels[idx],
-                            field.getSelectSubclasses(), false, false);
-                        sel.whereForeignKey(field.getBi1ToMElemFK(), sm.getObjectId(), 
-                            field.getDefiningMapping(), store);
+                    	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);
                     }
                 }
-                sel.select(rels[idx], subs, store, fetch, fetch.EAGER_JOIN, 
-                    resJoins[idx]);
+                if (!sel.isReadOnly()) {
+                	sel.select(rels[idx], subs, store, fetch, JDBCFetchConfiguration.EAGER_JOIN, resJoins[idx]);
+                }
             }
         });
 
         Result res = union.execute(store, fetch);
         try {
-            Object val = null;
-            if (res.next())
-                val = res.load(rels[res.indexOf()], store, fetch,
-                    resJoins[res.indexOf()]);
+            Object val = (res.next()) ? res.load(rels[res.indexOf()], store, fetch, resJoins[res.indexOf()]) : null;
             sm.storeObject(field.getIndex(), val);
         } finally {
             res.close();
@@ -837,7 +837,7 @@ public class RelationFieldStrategy
         // because it'll be in the primary table) and see if fk cols are null;
         // if inverse, then we have to do a sub-select to see if any inverse
         // objects point back to this field's owner
-        if (field.getJoinDirection() != field.JOIN_INVERSE) {
+        if (field.getJoinDirection() != FieldMapping.JOIN_INVERSE) {
             //### probably need some sort of subselect here on fk constants
             joins = join(joins, false);
             Column[] cols = field.getColumns();
@@ -846,8 +846,9 @@ public class RelationFieldStrategy
             else
                 sql.append(sel.getColumnAlias(cols[0], joins)).
                     append(" IS ").appendValue(null, cols[0]);
-        } else
+        } else {
             testInverseNull(sql, sel, joins, true);
+        }
     }
 
     public void appendIsNotNull(SQLBuffer sql, Select sel, Joins joins) {
@@ -855,7 +856,7 @@ public class RelationFieldStrategy
         // because it'll be in the primary table) and see if fk cols aren't
         // null; if inverse, then we have to do a sub-select to see if any
         // inverse objects point back to this field's owner
-        if (field.getJoinDirection() != field.JOIN_INVERSE) {
+        if (field.getJoinDirection() != FieldMapping.JOIN_INVERSE) {
             //### probably need some sort of subselect here on fk constants
             joins = join(joins, false);
             Column[] cols = field.getColumns();
@@ -886,30 +887,27 @@ public class RelationFieldStrategy
             sql.append("0 < ");
 
         ForeignKey fk = field.getForeignKey();
-        ContainerFieldStrategy.appendJoinCount(sql, sel, joins, dict, field,
-            fk);
+        ContainerFieldStrategy.appendJoinCount(sql, sel, joins, dict, field, fk);
     }
 
     public Joins join(Joins joins, boolean forceOuter) {
         // if we're not in an inverse object table join normally, otherwise
         // already traversed the relation; just join back to owner table
-        if (field.getJoinDirection() != field.JOIN_INVERSE)
+        if (field.getJoinDirection() != FieldMapping.JOIN_INVERSE)
             return field.join(joins, forceOuter, false);
         ClassMapping[] clss = field.getIndependentTypeMappings();
         if (clss.length != 1)
             throw RelationStrategies.uninversable(field);
         if (forceOuter)
             return joins.outerJoinRelation(field.getName(),
-                field.getForeignKey(), clss[0], field.getSelectSubclasses(), 
-                true, false);
+                field.getForeignKey(), clss[0], field.getSelectSubclasses(), true, false);
         return joins.joinRelation(field.getName(), field.getForeignKey(),
             clss[0], field.getSelectSubclasses(), true, false);
     }
 
-    public Joins joinRelation(Joins joins, boolean forceOuter,
-        boolean traverse) {
+    public Joins joinRelation(Joins joins, boolean forceOuter, boolean traverse) {
         // if this is an inverse mapping it's already joined to the relation
-        if (field.getJoinDirection() == field.JOIN_INVERSE)
+        if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE)
             return joins;
         ClassMapping[] clss = field.getIndependentTypeMappings();
         if (clss.length != 1) {
@@ -946,8 +944,7 @@ public class RelationFieldStrategy
             long id = res.getLong(col, joins);
             if (field.getObjectIdFieldTypeCode() == JavaTypes.LONG)
                 return id;
-            return store.newDataStoreId(id, relmapping, field.getPolymorphic() 
-                != ValueMapping.POLY_FALSE);
+            return store.newDataStoreId(id, relmapping, field.getPolymorphic() != ValueMapping.POLY_FALSE);
         }
 
         if (relmapping.isOpenJPAIdentity())
@@ -1000,27 +997,21 @@ public class RelationFieldStrategy
             fieldVal = store.getContext().getObjectId(fieldVal);
         if (fieldVal instanceof OpenJPAId)
             fieldVal = ((OpenJPAId) fieldVal).getIdObject();
-        if (relmapping.getObjectIdType() != null
-            && relmapping.getObjectIdType().isInstance(fieldVal)) {
+        if (relmapping.getObjectIdType() != null && relmapping.getObjectIdType().isInstance(fieldVal)) {
             Object[] pks = ApplicationIds.toPKValues(fieldVal, relmapping);
-            fieldVal = pks[relmapping.getField(j.getFieldIndex()).
-                getPrimaryKeyIndex()];
+            fieldVal = pks[relmapping.getField(j.getFieldIndex()).getPrimaryKeyIndex()];
         } else if (relmapping.getObjectIdType() == ObjectId.class && 
             relmapping.getPrimaryKeyFieldMappings()[0].getValueMapping().isEmbedded()) {
-            if (fieldVal == null)
-                return j.getJoinValue(savedFieldVal, col, store);
-            return j.getJoinValue(fieldVal, col, store);
+            return j.getJoinValue((fieldVal == null) ? savedFieldVal : fieldVal, col, store);
         }
         return j.getJoinValue(fieldVal, col, store);
     }
 
-    public Object getJoinValue(OpenJPAStateManager sm, Column col,
-        JDBCStore store) {
+    public Object getJoinValue(OpenJPAStateManager sm, Column col, JDBCStore store) {
         return getJoinValue(sm.fetch(field.getIndex()), col, store);
     }
 
-    public void setAutoAssignedValue(OpenJPAStateManager sm, JDBCStore store,
-        Column col, Object autoInc) {
+    public void setAutoAssignedValue(OpenJPAStateManager sm, JDBCStore store, Column col, Object autoInc) {
         throw new UnsupportedException();
     }
 
@@ -1048,8 +1039,7 @@ public class RelationFieldStrategy
         return UNSUPPORTED;
     }
 
-    public void loadEmbedded(OpenJPAStateManager sm, JDBCStore store,
-        JDBCFetchConfiguration fetch, Object val)
+    public void loadEmbedded(OpenJPAStateManager sm, JDBCStore store, JDBCFetchConfiguration fetch, Object val)
         throws SQLException {
         ClassMapping relMapping = field.getTypeMapping();
         Object oid;
@@ -1059,8 +1049,7 @@ public class RelationFieldStrategy
             oid = store.newDataStoreId(((Number) val).longValue(), relMapping,
                 field.getPolymorphic() != ValueMapping.POLY_FALSE);
         else {
-            Object[] pks = (getColumns().length == 1) ? new Object[]{ val }
-                : (Object[]) val;
+            Object[] pks = (getColumns().length == 1) ? new Object[]{ val } : (Object[]) val;
             boolean nulls = true;
             for (int i = 0; nulls && i < pks.length; i++)
                 nulls = pks[i] == null;
@@ -1068,17 +1057,15 @@ public class RelationFieldStrategy
                 oid = null;
             else {
                 oid = ApplicationIds.fromPKValues(pks, relMapping);
-                if (field.getPolymorphic() == ValueMapping.POLY_FALSE
-                    && oid instanceof OpenJPAId) {
-                    ((OpenJPAId) oid).setManagedInstanceType(relMapping.
-                        getDescribedType());
+                if (field.getPolymorphic() == ValueMapping.POLY_FALSE && oid instanceof OpenJPAId) {
+                    ((OpenJPAId) oid).setManagedInstanceType(relMapping.getDescribedType());
                 }
             }
         }
 
-        if (oid == null)
+        if (oid == null) {
             sm.storeObject(field.getIndex(), null);
-        else {
+        } else {
             if (JavaTypes.maybePC(field.getValue()) &&
                 field.getElement().getEmbeddedMetaData() == null) {
                 Object obj = store.find(oid, field, fetch);