Repository: cayenne
Updated Branches:
  refs/heads/master 0c3e3b68c -> 91eb2c0ae


CAY-2242 Fix from Matt Watson for multiple insertion case.


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/91eb2c0a
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/91eb2c0a
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/91eb2c0a

Branch: refs/heads/master
Commit: 91eb2c0aede06162de39ab27f73ccc467b14fc6e
Parents: 0c3e3b6
Author: Nikita Timofeev <stari...@gmail.com>
Authored: Fri Feb 24 09:56:29 2017 +0300
Committer: Nikita Timofeev <stari...@gmail.com>
Committed: Fri Feb 24 09:56:29 2017 +0300

----------------------------------------------------------------------
 .../access/DataDomainFlattenedBucket.java       | 67 +++++++++++++-------
 .../cayenne/access/VerticalInheritanceIT.java   | 27 ++++++++
 2 files changed, 71 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/91eb2c0a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainFlattenedBucket.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainFlattenedBucket.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainFlattenedBucket.java
index b88a341..900174e 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainFlattenedBucket.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainFlattenedBucket.java
@@ -108,29 +108,53 @@ class DataDomainFlattenedBucket {
             List<FlattenedArcKey> flattenedArcKeys = entry.getValue();
 
             DataNode node = 
parent.getDomain().lookupDataNode(dbEntity.getDataMap());
+
+            // TODO: O(N) lookup
+            InsertBatchQuery existingQuery = findInsertBatchQuery(queries, 
dbEntity);
             InsertBatchQuery newQuery = new InsertBatchQuery(dbEntity, 50);
-            boolean newQueryAdded = false;
 
-            // Here can be options with multiple arcs:
-            //  1. they can go as different columns in a single row
-            //  2. they can go as different rows in one batch
-            //  3. mix of both
+            // merge the snapshots of the FAKs by ObjectId for all ToOne 
relationships in case we have multiple Arcs per Object
+            Map<ObjectId, Map<String, Object>> toOneSnapshots = new 
HashMap<>();
+
+            // gather the list of the ToMany snapshots (these will actually be 
their own insert rows)
+            List<Map<String, Object>> toManySnapshots = new ArrayList<>();
+
             for (FlattenedArcKey flattenedArcKey : flattenedArcKeys) {
-                Map<String, Object> snapshot = 
flattenedArcKey.buildJoinSnapshotForInsert(node);
-                ObjectId objectId = null;
+                Map<String, Object> joinSnapshot = 
flattenedArcKey.buildJoinSnapshotForInsert(node);
+
+                if (flattenedArcKey.relationship.isToMany()) {
+                    toManySnapshots.add(joinSnapshot);
+                } else {
+                    ObjectId objectId = flattenedArcKey.id1.getSourceId();
+
+                    Map<String, Object> snapshot = 
toOneSnapshots.get(objectId);
+
+                    if (snapshot == null) {
+                        toOneSnapshots.put(objectId, joinSnapshot);
+                    } else {
+                        // merge joinSnapshot data with existing snapshot
+                        for (Map.Entry<String, Object> dbValue : 
joinSnapshot.entrySet()) {
+                            snapshot.put(dbValue.getKey(), dbValue.getValue());
+                        }
+                    }
+                }
+            }
+
+            // apply the merged ToOne snapshots information and possibly merge 
it with an existing BatchQueryRow
+            for (Map.Entry<ObjectId, Map<String, Object>> flattenedSnapshot : 
toOneSnapshots.entrySet()) {
+                ObjectId objectId = flattenedSnapshot.getKey();
+                Map<String, Object> snapshot = flattenedSnapshot.getValue();
 
-                // TODO: O(N) lookup
-                InsertBatchQuery existingQuery = findInsertBatchQuery(queries, 
dbEntity);
                 if (existingQuery != null) {
+
                     // TODO: O(N) lookup
-                    BatchQueryRow existingRow = 
findRowForObjectId(existingQuery.getRows(), flattenedArcKey.id1.getSourceId());
+                    BatchQueryRow existingRow = 
findRowForObjectId(existingQuery.getRows(), objectId);
                     // todo: do we need to worry about flattenedArcKey.id2 ?
 
                     if (existingRow != null) {
-                        objectId = existingRow.getObjectId();
                         List<DbAttribute> existingQueryDbAttributes = 
existingQuery.getDbAttributes();
 
-                        for (int i = 0; i < existingQueryDbAttributes.size(); 
i++) {
+                        for(int i=0; i < existingQueryDbAttributes.size(); 
i++) {
                             Object value = existingRow.getValue(i);
                             if (value != null) {
                                 
snapshot.put(existingQueryDbAttributes.get(i).getName(), value);
@@ -140,21 +164,18 @@ class DataDomainFlattenedBucket {
                 }
 
                 newQuery.add(snapshot, objectId);
+            }
 
-                if (existingQuery != null) {
-                    // replace inside arc loop, so next arc know about it
-                    queries.remove(existingQuery);
-                    queries.add(newQuery);
-                    newQueryAdded = true;
-                    // start clean query for the next arc
-                    newQuery = new InsertBatchQuery(dbEntity, 50);
-                }
+            // apply the ToMany snapshots as new BatchQueryRows
+            for(Map<String, Object> toManySnapshot : toManySnapshots) {
+                newQuery.add(toManySnapshot);
             }
 
-            if(!newQueryAdded) {
-                // if not replaced existing query already
-                queries.add(newQuery);
+            if (existingQuery != null) {
+                queries.remove(existingQuery);
             }
+
+            queries.add(newQuery);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/91eb2c0a/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
index 1f2d512..147e468 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
@@ -619,4 +619,31 @@ public class VerticalInheritanceIT extends ServerCase {
                assertEquals(other2, impl2.getOther2());
        }
 
+       @Test
+       public void 
testInsertTwoObjectsWithMultipleAttributeAndMultipleRelationship() {
+               IvOther other1 = context.newObject(IvOther.class);
+               other1.setName("other1");
+
+               IvOther other2 = context.newObject(IvOther.class);
+               other2.setName("other2");
+
+               IvImpl impl1 = context.newObject(IvImpl.class);
+               impl1.setName("Impl 1");
+               impl1.setAttr1("attr1");
+               impl1.setAttr2("attr2");
+               impl1.setOther1(other1);
+               impl1.setOther2(other2);
+
+               IvImpl impl2 = context.newObject(IvImpl.class);
+               impl2.setName("Impl 2");
+               impl2.setAttr1("attr1");
+               impl2.setAttr2("attr2");
+               impl2.setOther1(other1);
+               impl2.setOther2(other2);
+
+               context.commitChanges();
+
+               assertEquals(2, 
ObjectSelect.query(IvImpl.class).selectCount(context));
+       }
+
 }

Reply via email to