You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2009/09/24 11:00:13 UTC

svn commit: r818410 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/c...

Author: faywang
Date: Thu Sep 24 09:00:12 2009
New Revision: 818410

URL: http://svn.apache.org/viewvc?rev=818410&view=rev
Log:
OPENJPA-1253: support non-default uni-directional one to many map using foreign key strategy

Added:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC_U1M_Map_FK.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/Uni_1ToM_Map_FK.java
Modified:
    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-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/PersistenceMappingDefaults.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java

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=818410&r1=818409&r2=818410&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 Thu Sep 24 09:00:12 2009
@@ -86,18 +86,26 @@
         union.select(new Union.Selector() {
             public void select(Select sel, int idx) {
                 sel.select(_kcols);
-                sel.whereForeignKey(field.getJoinForeignKey(),
-                    sm.getObjectId(), field.getDefiningMapping(), store);
-                FieldMapping mapped = field.getMappedByMapping();
-                Joins joins = joinValueRelation(sel.newJoins(), vals[idx]);
-                
-                sel.select(vals[idx], field.getElementMapping().
-                    getSelectSubclasses(), store, fetch, eagerMode, joins);
-
-                //### cheat: result joins only care about the relation path;
-                //### thus we can use first mapping of union only
-                if (idx == 0)
-                    resJoins[1] = joins;
+                if (isUni1ToMFK()) {
+                    sel.whereForeignKey(field.getElementMapping().getForeignKey(),
+                        sm.getObjectId(), field.getElementMapping().getDeclaredTypeMapping(), store);
+                } else {
+                    sel.whereForeignKey(field.getJoinForeignKey(),
+                        sm.getObjectId(), field.getDefiningMapping(), store);
+                }
+                if (!isUni1ToMFK()) {
+                    Joins joins = joinValueRelation(sel.newJoins(), vals[idx]);
+                    sel.select(vals[idx], field.getElementMapping().
+                        getSelectSubclasses(), store, fetch, eagerMode, joins);
+
+                    //### cheat: result joins only care about the relation path;
+                    //### thus we can use first mapping of union only
+                    if (idx == 0)
+                        resJoins[1] = joins;
+                } else {
+                    sel.select(vals[idx], field.getElementMapping().
+                        getSelectSubclasses(), store, fetch, eagerMode, null);
+                }
             }
         });
         Result res = union.execute(store, fetch);
@@ -138,11 +146,12 @@
         ValueMapping val = field.getElementMapping();
         if (val.getTypeCode() != JavaTypes.PC || val.isEmbeddedPC())
             throw new MetaDataException(_loc.get("not-relation", val));
-        FieldMapping mapped = field.getMappedByMapping();
         
-        if (mapped != null) // map to the owner table
-            handleMappedBy(adapt);
-        else { 
+        FieldMapping mapped = field.getMappedByMapping();
+        if ((isUni1ToMFK() && !isBi1ToMJT()) || mapped != null) { 
+            // map to the owner table
+            handleMappedByForeignKey(adapt);
+        } else if ((!isUni1ToMFK() && isBi1ToMJT()) || mapped == null){ 
             // map to a separate table
             field.mapJoin(adapt, true);
             if (val.getTypeMapping().isMapped()) {
@@ -178,13 +187,16 @@
         throws SQLException {
         if (map == null || map.isEmpty())
             return;
+        
         if (field.getMappedBy() != null)
             return;
 
-        Row row = rm.getSecondaryRow(field.getTable(), Row.ACTION_INSERT);
-        row.setForeignKey(field.getJoinForeignKey(), field.getJoinColumnIO(),
-            sm);
-
+        Row row = null;
+        if (!isUni1ToMFK()) {
+            row = rm.getSecondaryRow(field.getTable(), Row.ACTION_INSERT);
+            row.setForeignKey(field.getJoinForeignKey(), field.getJoinColumnIO(),
+                sm);
+        }
         ValueMapping key = field.getKeyMapping();
         ValueMapping val = field.getElementMapping();
         StoreContext ctx = store.getContext();
@@ -192,21 +204,30 @@
         Map.Entry entry;
         for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) {
             entry = (Map.Entry) itr.next();
-            HandlerStrategies.set(key, entry.getKey(), store, row, _kcols,
-                _kio, true);
             valsm = RelationStrategies.getStateManager(entry.getValue(),
                 ctx);
-            val.setForeignKey(row, valsm);
+            if (isUni1ToMFK()){
+                row = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+                    Row.ACTION_UPDATE, valsm, true);
+                row.wherePrimaryKey(valsm);
+                val.setForeignKey(row, sm);
+            } else {
+                val.setForeignKey(row, valsm);
+            }
+            HandlerStrategies.set(key, entry.getKey(), store, row, _kcols,
+                    _kio, true);
             
-            // So far we poplulated the key/value of each
+            // So far we populated the key/value of each
             // map element owned by the entity.
             // In the case of ToMany, and both sides
             // use Map to represent the relation,
             // we need to populate the key value of the owner
             // from the view point of the owned side
             PersistenceCapable obj = sm.getPersistenceCapable();
-            if (!populateKey(row, valsm, obj, ctx, rm, store))
-                rm.flushSecondaryRow(row);
+            if (!populateKey(row, valsm, obj, ctx, rm, store)) {
+                if (!isUni1ToMFK())
+                    rm.flushSecondaryRow(row);
+            }
         }
     }
     
@@ -249,36 +270,66 @@
         boolean canChange = val.getForeignKey().isLogical();
         Object mkey;
         if (canChange && !change.isEmpty()) {
-            Row changeRow = rm.getSecondaryRow(field.getTable(),
-                Row.ACTION_UPDATE);
-            changeRow.whereForeignKey(field.getJoinForeignKey(), sm);
-
+            Row changeRow = null;
+            if (!isUni1ToMFK()) {
+                changeRow = rm.getSecondaryRow(field.getTable(),
+                    Row.ACTION_UPDATE);
+                changeRow.whereForeignKey(field.getJoinForeignKey(), sm);
+            }
+            
             for (Iterator itr = change.iterator(); itr.hasNext();) {
                 mkey = itr.next();
-                HandlerStrategies.where(key, mkey, store, changeRow, _kcols);
                 valsm = RelationStrategies.getStateManager(map.get(mkey), ctx);
-                val.setForeignKey(changeRow, valsm);
-                rm.flushSecondaryRow(changeRow);
+                if (isUni1ToMFK()){
+                    changeRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+                        Row.ACTION_UPDATE, valsm, true);
+                    changeRow.wherePrimaryKey(valsm);
+                    val.setForeignKey(changeRow, sm);
+                } else {
+                    val.setForeignKey(changeRow, valsm);
+                }
+                
+                HandlerStrategies.where(key, mkey, store, changeRow, _kcols);
+                if (!isUni1ToMFK())
+                    rm.flushSecondaryRow(changeRow);
             }
         }
 
         // delete the removes
         Collection rem = ct.getRemoved();
         if (!rem.isEmpty() || (!canChange && !change.isEmpty())) {
-            Row delRow = rm.getSecondaryRow(field.getTable(),
-                Row.ACTION_DELETE);
-            delRow.whereForeignKey(field.getJoinForeignKey(), sm);
-
+            Row delRow = null;
+            if (!isUni1ToMFK()) {
+                delRow = rm.getSecondaryRow(field.getTable(),
+                    Row.ACTION_DELETE);
+                delRow.whereForeignKey(field.getJoinForeignKey(), sm);
+            }
             for (Iterator itr = rem.iterator(); itr.hasNext();) {
-                HandlerStrategies.where(key, itr.next(), store, delRow,
+                mkey = itr.next();
+                if (isUni1ToMFK()){
+                    delRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+                        Row.ACTION_UPDATE, sm, true);
+                    val.setForeignKey(delRow, null);
+                } 
+                
+                HandlerStrategies.where(key, mkey, store, delRow,
                     _kcols);
-                rm.flushSecondaryRow(delRow);
+                if (!isUni1ToMFK())
+                    rm.flushSecondaryRow(delRow);
             }
             if (!canChange && !change.isEmpty()) {
                 for (Iterator itr = change.iterator(); itr.hasNext();) {
+                    mkey = itr.next();
+                    if (isUni1ToMFK()){
+                        delRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+                            Row.ACTION_UPDATE, sm, true);
+                        val.setForeignKey(delRow, null);
+                    } 
+
                     HandlerStrategies.where(key, itr.next(), store, delRow,
                         _kcols);
-                    rm.flushSecondaryRow(delRow);
+                    if (!isUni1ToMFK())
+                        rm.flushSecondaryRow(delRow);
                 }
             }
         }
@@ -286,28 +337,47 @@
         // insert the adds
         Collection add = ct.getAdded();
         if (!add.isEmpty() || (!canChange && !change.isEmpty())) {
-            Row addRow = rm.getSecondaryRow(field.getTable(),
-                Row.ACTION_INSERT);
-            addRow.setForeignKey(field.getJoinForeignKey(),
-                field.getJoinColumnIO(), sm);
-
+            Row addRow = null;
+            if (!isUni1ToMFK()) {
+                addRow = rm.getSecondaryRow(field.getTable(),
+                        Row.ACTION_INSERT);
+                addRow.setForeignKey(field.getJoinForeignKey(),
+                        field.getJoinColumnIO(), sm);
+            }
             for (Iterator itr = add.iterator(); itr.hasNext();) {
                 mkey = itr.next();
+                valsm = RelationStrategies.getStateManager(map.get(mkey), ctx);
+                if (isUni1ToMFK()){
+                    addRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+                        Row.ACTION_UPDATE, valsm, true);
+                    addRow.wherePrimaryKey(valsm);
+                    val.setForeignKey(addRow, sm);
+                } else {
+                    val.setForeignKey(addRow, valsm);
+                }
+                
                 HandlerStrategies.set(key, mkey, store, addRow, _kcols,
                     _kio, true);
-                valsm = RelationStrategies.getStateManager(map.get(mkey), ctx);
-                val.setForeignKey(addRow, valsm);
-                rm.flushSecondaryRow(addRow);
+                if (!isUni1ToMFK())
+                    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 (isUni1ToMFK()){
+                        addRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+                            Row.ACTION_UPDATE, valsm, true);
+                        addRow.wherePrimaryKey(valsm);
+                        val.setForeignKey(addRow, sm);
+                    } else {
+                        val.setForeignKey(addRow, valsm);
+                    }
+                    
                     HandlerStrategies.set(key, mkey, store, addRow, _kcols,
                         _kio, true);
-                    valsm = RelationStrategies.getStateManager(map.get(mkey),
-                        ctx);
-                    val.setForeignKey(addRow, valsm);
-                    rm.flushSecondaryRow(addRow);
+                    if (!isUni1ToMFK())
+                        rm.flushSecondaryRow(addRow);
                 }
             }
         }
@@ -353,7 +423,7 @@
     
     public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
         throws SQLException {
-        if (field.getMappedBy() != null)
+        if (field.getMappedBy() != null || isUni1ToMFK())
             return;
         super.delete(sm, store, rm);
     }

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=818410&r1=818409&r2=818410&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 Thu Sep 24 09:00:12 2009
@@ -22,6 +22,7 @@
 import java.util.Collection;
 import java.util.Map;
 
+import org.apache.openjpa.conf.OpenJPAConfiguration;
 import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.enhance.ReflectingPersistenceCapable;
 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
@@ -31,6 +32,7 @@
 import org.apache.openjpa.jdbc.meta.FieldStrategy;
 import org.apache.openjpa.jdbc.meta.Strategy;
 import org.apache.openjpa.jdbc.meta.ValueMapping;
+import org.apache.openjpa.jdbc.meta.ValueMappingInfo;
 import org.apache.openjpa.jdbc.schema.ForeignKey;
 import org.apache.openjpa.jdbc.sql.Joins;
 import org.apache.openjpa.jdbc.sql.Result;
@@ -42,6 +44,7 @@
 import org.apache.openjpa.kernel.StoreContext;
 import org.apache.openjpa.lib.log.Log;
 import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.util.MetaDataException;
 
@@ -63,10 +66,44 @@
     private static final Localizer _loc = Localizer.forPackage
         (MapTableFieldStrategy.class);
 
+    private Boolean _isNonDefaultMappingAllowed = null;
+    private Boolean _isBi1ToMJT = null;
+    private Boolean _isUni1ToMFK = null;
+
     public FieldMapping getFieldMapping() {
         return field;
     }
 
+    private void isNonDefaultMapping() {
+        FieldMapping mapped = field.getMappedByMapping();
+        if (isNonDefaultMappingAllowed() && 
+            field.getAssociationType() == FieldMetaData.ONE_TO_MANY &&
+            field.getValueInfo().getColumns().size() > 0) {
+            if (mapped != null) {
+                _isBi1ToMJT = true;
+                _isUni1ToMFK = false;
+            } else {
+                _isBi1ToMJT = false;
+                _isUni1ToMFK = true;
+            }
+        } else {
+            _isBi1ToMJT = false;
+            _isUni1ToMFK = false;
+        }
+    }
+    
+    protected boolean isBi1ToMJT() {
+        if (_isBi1ToMJT == null)
+            isNonDefaultMapping();
+        return _isBi1ToMJT;
+    }
+    
+    protected boolean isUni1ToMFK() {
+        if (_isUni1ToMFK == null)
+            isNonDefaultMapping();
+        return _isUni1ToMFK;
+    }
+
     public ClassMapping[] getIndependentKeyMappings(boolean traverse) {
         return (traverse) ? field.getKeyMapping().getIndependentTypeMappings()
             : ClassMapping.EMPTY_MAPPINGS;
@@ -108,8 +145,23 @@
             throw new MetaDataException(_loc.get("not-map", field));
         if (field.getKey().getValueMappedBy() != null)
             throw new MetaDataException(_loc.get("mapped-by-key", field));
+
+        // Non-default mapping Uni-/OneToMany/ForeignKey allows schema components
+        if (isNonDefaultMappingAllowed() && 
+            field.getAssociationType() == FieldMetaData.ONE_TO_MANY && 
+            field.getMappedByMapping() == null)  
+                return;
         field.getValueInfo().assertNoSchemaComponents(field, !adapt);
     }
+    
+    protected boolean isNonDefaultMappingAllowed() {
+        if (_isNonDefaultMappingAllowed == null) {
+            OpenJPAConfiguration conf = field.getRepository().getConfiguration();
+            _isNonDefaultMappingAllowed = field.getRepository().
+                getMetaDataFactory().getDefaults().isNonDefaultMappingAllowed(conf);
+        }
+        return _isNonDefaultMappingAllowed;
+    }
 
     public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
         throws SQLException {
@@ -182,12 +234,11 @@
         return ClassMapping.EMPTY_MAPPINGS;
     }
     
-    protected void handleMappedBy(boolean adapt){
+    protected void handleMappedByForeignKey(boolean adapt){
         boolean criteria = field.getValueInfo().getUseClassCriteria();
         // check for named inverse
         FieldMapping mapped = field.getMappedByMapping();
         if (mapped != null) {
-            field.getMappingInfo().assertNoSchemaComponents(field, !adapt);
             field.getValueInfo().assertNoSchemaComponents(field, !adapt);
             mapped.resolve(mapped.MODE_META | mapped.MODE_MAPPING);
 
@@ -229,6 +280,21 @@
 
             field.setUseClassCriteria(criteria);
             return;
+        } else {
+            // Uni-/OneToMany/ForeingKey
+            ValueMapping val = field.getElementMapping();
+            val.getValueInfo().setColumns(field.getValueInfo().getColumns());
+            if (val.getTypeMapping().isMapped()) {
+                ValueMappingInfo vinfo = val.getValueInfo();
+                ForeignKey fk = vinfo.getTypeJoin(val, null, false, adapt);
+                val.setForeignKey(fk);
+                val.setColumnIO(vinfo.getColumnIO());
+            } else
+                RelationStrategies.mapRelationToUnmappedPC(val, "value", adapt);
+
+            val.mapConstraints("value", adapt);
+            
+            return;
         }
 /*
         // this is necessary to support openjpa 3 mappings, which didn't

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=818410&r1=818409&r2=818410&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 Thu Sep 24 09:00:12 2009
@@ -375,14 +375,15 @@
             }
             
             if (_biOneToManyJoinTable != -1) { // also need to update the join table
-                PersistenceCapable inversePC = (PersistenceCapable)sm.fetchObject(_biOneToManyJoinTable);
+                PersistenceCapable invPC = (PersistenceCapable)sm.fetchObject(_biOneToManyJoinTable);
                 Row secondaryRow = null;
-                if (inversePC != null) {
+                if (invPC != null) {
                     secondaryRow = rm.getSecondaryRow(_biOneToManyJoinFK.getTable(),
                         Row.ACTION_INSERT);
                     secondaryRow.setForeignKey(_biOneToManyElemFK, null, sm);
                     secondaryRow.setForeignKey(_biOneToManyJoinFK, null, 
-                        (OpenJPAStateManager)inversePC.pcGetStateManager());
+                        RelationStrategies.getStateManager(invPC,
+                        store.getContext()));
                 } else { 
                     secondaryRow = rm.getSecondaryRow(_biOneToManyJoinFK.getTable(),
                             Row.ACTION_DELETE);

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java?rev=818410&r1=818409&r2=818410&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java Thu Sep 24 09:00:12 2009
@@ -185,7 +185,7 @@
         DBDictionary dict = field.getMappingRepository().getDBDictionary();
         String keyName = null;
         if (mapped != null) {         
-            handleMappedBy(adapt);
+            handleMappedByForeignKey(adapt);
             keyName = dict.getValidColumnName("vkey", field.getTable());
          } else {
             field.mapJoin(adapt, true);

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/PersistenceMappingDefaults.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/PersistenceMappingDefaults.java?rev=818410&r1=818409&r2=818410&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/PersistenceMappingDefaults.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/PersistenceMappingDefaults.java Thu Sep 24 09:00:12 2009
@@ -214,16 +214,18 @@
         // otherwise jpa always uses <field>_<pkcol> for column name, even
         // when only one col
         if (target instanceof Column) {
-            if (elem)
-                name = vm.getFieldMapping().getName();
+            if (name == null) {
+                name = col.getName();
+            } else {
+                if (elem)
+                    name = vm.getFieldMapping().getName();
+                if (isRemoveHungarianNotation())
+                    name = removeHungarianNotation(name);
+                name = dict.combineNames(name, ((Column)target).getName());
 
-            if (isRemoveHungarianNotation())
-                name = removeHungarianNotation(name);
-            
-            name = dict.combineNames(name, ((Column)target).getName());
-            
-            // No need to check for uniqueness.
-            name = dict.getValidColumnName(name, local, false);
+                // No need to check for uniqueness.
+                name = dict.getValidColumnName(name, local, false);
+            }
             col.setName(name);
         }
     }

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC_U1M_Map_FK.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC_U1M_Map_FK.java?rev=818410&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC_U1M_Map_FK.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC_U1M_Map_FK.java Thu Sep 24 09:00:12 2009
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.persistence.compat;
+
+import java.util.List;
+
+import javax.persistence.*;
+
+@Entity
+public class EntityC_U1M_Map_FK {
+
+    @Id
+    @GeneratedValue
+    private long id;
+
+    private String name;
+
+    public long getId() { 
+        return id; 
+    }
+
+    public String getName() { 
+        return name; 
+    }
+
+    public void setName(String name) { 
+        this.name = name; 
+    }
+
+    public int hashCode() {
+        return name.hashCode() + (int)id;
+    }
+    
+    public boolean equals(Object o) {
+        if (!(o instanceof EntityC_U1M_Map_FK)) return false;
+        EntityC_U1M_Map_FK c = (EntityC_U1M_Map_FK)o;
+        if (!c.name.equals(name)) return false;
+        if (c.id != id) return false;
+        return true;
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC_U1M_Map_FK.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java?rev=818410&r1=818409&r2=818410&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java Thu Sep 24 09:00:12 2009
@@ -392,7 +392,89 @@
         em.clear();
     }
     
+    public void testOneToManyMapRelation() {
+        List<Class<?>> types = new ArrayList<Class<?>>();
+        types.add(EntityC_U1M_Map_FK.class);
+        types.add(Uni_1ToM_Map_FK.class);
+        OpenJPAEntityManagerFactorySPI emf = createEMF2_0(types);
+        EntityManager em = emf.createEntityManager();
+        
+        try {
+            // trigger table creation
+            em.getTransaction().begin();
+            em.getTransaction().commit();
+            assertSQLFragnments(sql, "CREATE TABLE EntityC_U1M_Map_FK", "Uni1MFK_ID", "KEY0");
+            crudUni1MMapFK(em);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail("OneToMany mapping failed with exception message: " + e.getMessage());
+        } finally {
+            em.close();
+            emf.close();            
+        }
+    }
+
+    public void crudUni1MMapFK(EntityManager em) {
+        //create
+        Uni_1ToM_Map_FK u = new Uni_1ToM_Map_FK();
+        u.setName("uni1mfk");
+        Map<String, EntityC_U1M_Map_FK> cs = new HashMap<String, EntityC_U1M_Map_FK>();
+        EntityC_U1M_Map_FK c1 = new EntityC_U1M_Map_FK();
+        c1.setName("c1");
+        cs.put(c1.getName(), c1);
+        EntityC_U1M_Map_FK c2 = new EntityC_U1M_Map_FK();
+        c2.setName("c2");
+        cs.put(c2.getName(), c2);
+        u.setEntityCs(cs);
+        
+        em.persist(u);
+        em.persist(c1);
+        em.persist(c2);
+        em.getTransaction().begin();
+        em.getTransaction().commit();
+
+        //update by adding a new C
+        cs = u.getEntityCs();
+        u.setName("uni1mfk_new");
+        EntityC_U1M_Map_FK c3 = new EntityC_U1M_Map_FK();
+        c3.setName("c3");
+        cs.put(c3.getName(), c3);
+        em.persist(c3);
+
+        em.getTransaction().begin();
+        em.getTransaction().commit();
+        
+        // update by removing a c and then add this c to a new u
+        em.getTransaction().begin();
+        EntityC_U1M_Map_FK c4 = cs.remove("c1");
+        
+        Uni_1ToM_Map_FK u2 = new Uni_1ToM_Map_FK();
+        u2.setName("uni1mfk2");
+        Map<String, EntityC_U1M_Map_FK> cs2 = new HashMap<String, EntityC_U1M_Map_FK>();
+        cs2.put(c4.getName(), c4);
+        u2.setEntityCs(cs2);
+        em.persist(u2);
+        em.getTransaction().commit();
+        em.clear();
+        
+        //query
+        Query q = em.createQuery("SELECT u FROM Uni_1ToM_Map_FK u where u.name='uni1mfk_new'");
+        Uni_1ToM_Map_FK u1 = (Uni_1ToM_Map_FK)q.getSingleResult();
+        assertEquals(u, u1);
+        em.clear();
 
+        //find
+        long id = u1.getId();
+        Uni_1ToM_Map_FK findU = em.find(Uni_1ToM_Map_FK.class, id);
+        assertEquals(u, findU);
+        
+        //remove
+        em.getTransaction().begin();
+        em.remove(findU);
+        em.getTransaction().commit();
+    }
+    
+    
     private OpenJPAEntityManagerFactorySPI createEMF2_0(List<Class<?>> types) {
         Map<Object,Object> map = new HashMap<Object,Object>();
         map.put("openjpa.jdbc.JDBCListeners", 

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/Uni_1ToM_Map_FK.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/Uni_1ToM_Map_FK.java?rev=818410&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/Uni_1ToM_Map_FK.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/Uni_1ToM_Map_FK.java Thu Sep 24 09:00:12 2009
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.persistence.compat;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.*;
+
+//non-default mapping
+//Sec 11.1.36, Example 3: 
+//    Unidirectional One-to-Many association using a foreign key mapping
+//    In Customer class:
+//    @OneToMany(orphanRemoval=true)
+//    @JoinColumn(name="CUST_ID") // join column is in table for Order
+//    public Set<Order> getOrders() {return orders;}
+
+@Entity
+public class Uni_1ToM_Map_FK {
+
+    @Id
+    @GeneratedValue
+    private long id;
+
+    private String name;
+
+    @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
+    @JoinColumn(name="Uni1MFK_ID")
+    private Map<String, EntityC_U1M_Map_FK> entityCs = null;
+    
+    public long getId() { 
+        return id; 
+    }
+
+    public String getName() { 
+        return name; 
+    }
+
+    public void setName(String name) { 
+        this.name = name; 
+    }
+
+    public Map<String, EntityC_U1M_Map_FK> getEntityCs() { 
+        return entityCs; 
+    }
+
+    public void setEntityCs(Map<String, EntityC_U1M_Map_FK> entityCs) { 
+        this.entityCs = entityCs; 
+    }
+
+    public int hashCode() {
+        return name.hashCode();
+    }
+    
+    public boolean equals(Object o) {
+        if (!(o instanceof Uni_1ToM_Map_FK)) return false;
+        Uni_1ToM_Map_FK b = (Uni_1ToM_Map_FK)o;
+        if (!b.name.equals(name)) return false;
+        if (b.entityCs.size() != entityCs.size()) return false;
+        Collection<EntityC_U1M_Map_FK> coll = b.entityCs.values();
+        for (EntityC_U1M_Map_FK c : coll) {
+            if (!b.entityCs.get(c.getName()).equals(entityCs.get(c.getName())))
+                return false;
+        }
+        return true;
+    }
+}