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/01/21 07:50:17 UTC

svn commit: r736245 - in /openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats: HandlerRelationMapTableFieldStrategy.java MapTableFieldStrategy.java RelationRelationMapTableFieldStrategy.java

Author: faywang
Date: Tue Jan 20 22:50:16 2009
New Revision: 736245

URL: http://svn.apache.org/viewvc?rev=736245&view=rev
Log:
OPENJPA-851: ManyToMany Map support

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/RelationRelationMapTableFieldStrategy.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=736245&r1=736244&r2=736245&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 20 22:50:16 2009
@@ -25,6 +25,7 @@
 import org.apache.openjpa.meta.*;
 import org.apache.openjpa.kernel.*;
 import org.apache.openjpa.util.*;
+import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.jdbc.meta.*;
 import org.apache.openjpa.jdbc.kernel.*;
 import org.apache.openjpa.jdbc.schema.*;
@@ -88,9 +89,7 @@
                 sel.whereForeignKey(field.getJoinForeignKey(),
                     sm.getObjectId(), field.getDefiningMapping(), store);
                 FieldMapping mapped = field.getMappedByMapping();
-                Joins joins = null;
-                if (mapped == null)
-                    joins = joinValueRelation(sel.newJoins(), vals[idx]);
+                Joins joins = joinValueRelation(sel.newJoins(), vals[idx]);
                 
                 sel.select(vals[idx], field.getElementMapping().
                     getSelectSubclasses(), store, fetch, eagerMode, joins);
@@ -123,7 +122,10 @@
 
     public Joins joinValueRelation(Joins joins, ClassMapping val) {
         ValueMapping vm = field.getElementMapping();
-        return joins.joinRelation(field.getName(), vm.getForeignKey(val), val,
+        ForeignKey fk = vm.getForeignKey(val);
+        if (fk == null)
+            return null;
+        return joins.joinRelation(field.getName(), fk, val,
             vm.getSelectSubclasses(), false, false);
     }
 
@@ -195,9 +197,25 @@
             valsm = RelationStrategies.getStateManager(entry.getValue(),
                 ctx);
             val.setForeignKey(row, valsm);
-            rm.flushSecondaryRow(row);
+            
+            // So far we poplulated 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);
         }
     }
+    
+    public void setKey(Object keyObj, JDBCStore store, Row row) 
+        throws SQLException {
+        ValueMapping key = field.getKeyMapping();
+        HandlerStrategies.set(key, keyObj, store, row, _kcols,
+            _kio, true);
+    }
 
     public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
         throws SQLException {

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=736245&r1=736244&r2=736245&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 20 22:50:16 2009
@@ -19,21 +19,26 @@
 package org.apache.openjpa.jdbc.meta.strats;
 
 import java.sql.SQLException;
+import java.util.Collection;
 import java.util.Map;
 
+import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
 import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.meta.ClassMapping;
 import org.apache.openjpa.jdbc.meta.FieldMapping;
 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.schema.ForeignKey;
 import org.apache.openjpa.jdbc.sql.Joins;
 import org.apache.openjpa.jdbc.sql.Result;
 import org.apache.openjpa.jdbc.sql.Row;
+import org.apache.openjpa.jdbc.sql.RowImpl;
 import org.apache.openjpa.jdbc.sql.RowManager;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
+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.JavaTypes;
@@ -213,8 +218,8 @@
                     log.info(_loc.get("coll-owner", field, mapped));
                 ValueMapping elem = mapped.getElementMapping();
                 ForeignKey fk = elem.getForeignKey();
-                field.setForeignKey(fk);
                 field.setJoinForeignKey(fk);
+                field.getElementMapping().setForeignKey(mapped.getJoinForeignKey());
             } else
                 throw new MetaDataException(_loc.get("not-inv-relation",
                     field, mapped));
@@ -249,4 +254,51 @@
                 return false;
         return true;
     }
+
+    protected boolean populateKey(Row row, OpenJPAStateManager valsm, Object obj,
+            StoreContext ctx, RowManager rm, JDBCStore store) throws SQLException {
+        ClassMapping meta = (ClassMapping)valsm.getMetaData();
+        FieldMapping fm = getFieldMapping(meta);
+        if (fm == null) 
+            return false;
+        Map mapObj = (Map)valsm.fetchObject(fm.getIndex());
+        Collection<Map.Entry> entrySets = mapObj.entrySet();
+        boolean found = false;
+        for (Map.Entry entry : entrySets) {
+            if (entry.getValue() == obj) {
+                Row newRow = (Row) ((RowImpl)row).clone();
+                Object keyObj = entry.getKey();
+                Strategy strat = fm.getStrategy();
+                if (strat instanceof HandlerRelationMapTableFieldStrategy) {
+                    HandlerRelationMapTableFieldStrategy hrStrat = 
+                        (HandlerRelationMapTableFieldStrategy) strat;
+                    hrStrat.setKey(keyObj, store, newRow);
+                } else if (keyObj instanceof PersistenceCapable) {
+                    OpenJPAStateManager keysm = 
+                        RelationStrategies.getStateManager(entry.getKey(), ctx);
+                    ValueMapping key = fm.getKeyMapping();
+                    if (keysm != null) 
+                        key.setForeignKey(newRow, keysm);
+                    else
+                        key.setForeignKey(newRow, null);
+                } 
+                rm.flushSecondaryRow(newRow);
+                found = true;
+            }
+        }
+        if (found)
+            return true;
+        return false;        
+    }
+
+    private FieldMapping getFieldMapping(ClassMapping meta) {
+        FieldMapping[] fields = meta.getFieldMappings();
+        for (int i = 0; i < fields.length; i++) {
+            ValueMapping val = fields[i].getValueMapping();
+            if (fields[i].getMappedByMetaData() == field && 
+                    val.getDeclaredTypeCode() == JavaTypes.MAP)
+                return fields[i];
+        }
+        return null;
+    }
 }

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=736245&r1=736244&r2=736245&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 Tue Jan 20 22:50:16 2009
@@ -25,6 +25,7 @@
 import org.apache.openjpa.meta.*;
 import org.apache.openjpa.kernel.*;
 import org.apache.openjpa.util.*;
+import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.jdbc.meta.*;
 import org.apache.openjpa.jdbc.kernel.*;
 import org.apache.openjpa.jdbc.schema.*;
@@ -111,9 +112,7 @@
                 // order before select in case we're faking union with
                 // multiple selects; order vals used to merge results
                 FieldMapping mapped = field.getMappedByMapping();
-                Joins joins = null;
-                if (mapped == null)
-                    joins = joinValueRelation(sel.newJoins(), vals[idx]);
+                Joins joins = joinValueRelation(sel.newJoins(), vals[idx]);
                 sel.orderBy(field.getKeyMapping().getColumns(), true, true);
                 sel.select(vals[idx], field.getElementMapping().
                     getSelectSubclasses(), store, fetch, eagerMode, joins);
@@ -166,7 +165,10 @@
 
     public Joins joinValueRelation(Joins joins, ClassMapping val) {
         ValueMapping vm = field.getElementMapping();
-        return joins.joinRelation(field.getName(), vm.getForeignKey(val), val,
+        ForeignKey fk = vm.getForeignKey(val);
+        if (fk == null)
+            return null;
+        return joins.joinRelation(field.getName(), fk, val,
             vm.getSelectSubclasses(), false, false);
     }
 
@@ -180,13 +182,17 @@
         if (val.getTypeCode() != JavaTypes.PC || val.isEmbeddedPC())
             throw new MetaDataException(_loc.get("not-relation", val));
         FieldMapping mapped = field.getMappedByMapping();
-        if (mapped != null)         
+        DBDictionary dict = field.getMappingRepository().getDBDictionary();
+        String keyName = null;
+        if (mapped != null) {         
             handleMappedBy(adapt);
-        else {
+            keyName = dict.getValidColumnName("vkey", field.getTable());
+         } else {
             field.mapJoin(adapt, true);
             mapTypeJoin(val, "value", adapt);
+            keyName = dict.getValidColumnName("key", field.getTable());
         }
-        mapTypeJoin(key, "key", adapt);
+        mapTypeJoin(key, keyName, adapt);
 
         field.mapPrimaryKey(adapt);
     }
@@ -211,10 +217,11 @@
 
     public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
         throws SQLException {
-        insert(sm, rm, (Map) sm.fetchObject(field.getIndex()));
+        insert(sm, rm, (Map) sm.fetchObject(field.getIndex()), store);
     }
 
-    private void insert(OpenJPAStateManager sm, RowManager rm, Map map)
+    private void insert(OpenJPAStateManager sm, RowManager rm, Map map, 
+        JDBCStore store)
         throws SQLException {
         if (map == null || map.isEmpty())
             return;
@@ -237,7 +244,16 @@
             valsm = RelationStrategies.getStateManager(entry.getValue(), ctx);
             key.setForeignKey(row, keysm);
             val.setForeignKey(row, valsm);
-            rm.flushSecondaryRow(row);
+            
+            // so far, we poplulated 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);
         }
     }
 
@@ -257,7 +273,7 @@
         // if no fine-grained change tracking then just delete and reinsert
         if (ct == null || !ct.isTracking()) {
             delete(sm, store, rm);
-            insert(sm, rm, map);
+            insert(sm, rm, map, store);
             return;
         }