You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2018/05/16 14:44:21 UTC

cayenne git commit: Fix flattened toOne relationship update

Repository: cayenne
Updated Branches:
  refs/heads/master b31702618 -> a0b06f45f


Fix flattened toOne relationship update


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

Branch: refs/heads/master
Commit: a0b06f45f3cf834aed825ff3b96e9ac651517b25
Parents: b317026
Author: Nikita Timofeev <st...@gmail.com>
Authored: Wed May 16 17:43:47 2018 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Wed May 16 17:43:47 2018 +0300

----------------------------------------------------------------------
 .../cayenne/access/DataDomainSyncBucket.java    | 71 +++++++-------------
 .../cayenne/access/DataDomainUpdateBucket.java  | 14 +++-
 .../cayenne/access/DbEntityClassDescriptor.java | 15 ++++-
 .../cayenne/access/VerticalInheritanceIT.java   | 20 +++++-
 4 files changed, 70 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/a0b06f45/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainSyncBucket.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainSyncBucket.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainSyncBucket.java
index 7c25ab5..4e9dd0d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainSyncBucket.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainSyncBucket.java
@@ -97,48 +97,35 @@ abstract class DataDomainSyncBucket {
         descriptorsByDbEntity = new HashMap<>(objectsByDescriptor.size() * 2);
 
         for (ClassDescriptor descriptor : objectsByDescriptor.keySet()) {
+            addSpannedDbEntities(descriptor);
+        }
+    }
 
-            // root DbEntity
-            {
-                DbEntityClassDescriptor dbEntityDescriptor = new DbEntityClassDescriptor(descriptor);
-                DbEntity dbEntity = dbEntityDescriptor.getDbEntity();
+    void addSpannedDbEntities(ClassDescriptor descriptor) {
+        // root DbEntity
+        addDescriptor(descriptor, new DbEntityClassDescriptor(descriptor));
 
-                Collection<DbEntityClassDescriptor> descriptors = descriptorsByDbEntity.get(dbEntity);
-                if (descriptors == null) {
-                    descriptors = new ArrayList<>(1);
-                    dbEntities.add(dbEntity);
-                    descriptorsByDbEntity.put(dbEntity, descriptors);
-                }
-
-                if (!containsClassDescriptor(descriptors, descriptor)) {
-                    descriptors.add(dbEntityDescriptor);
-                }
+        // secondary DbEntities...
+        // Note that this logic won't allow flattened attributes to span multiple databases...
+        for (ObjAttribute objAttribute : descriptor.getEntity().getAttributes()) {
+            if (objAttribute.isFlattened()) {
+                addDescriptor(descriptor, new DbEntityClassDescriptor(descriptor, objAttribute));
             }
+        }
+    }
 
-            // secondary DbEntities...
-
-            // Note that this logic won't allow flattened attributes to span multiple databases...
-            for (ObjAttribute objAttribute : descriptor.getEntity().getAttributes()) {
-
-                if (objAttribute.isFlattened()) {
-                    DbEntityClassDescriptor dbEntityDescriptor = new DbEntityClassDescriptor(
-                            descriptor,
-                            objAttribute);
-
-                    DbEntity dbEntity = dbEntityDescriptor.getDbEntity();
-                    Collection<DbEntityClassDescriptor> descriptors = descriptorsByDbEntity.get(dbEntity);
+    void addDescriptor(ClassDescriptor descriptor, DbEntityClassDescriptor dbEntityDescriptor) {
+        DbEntity dbEntity = dbEntityDescriptor.getDbEntity();
+        Collection<DbEntityClassDescriptor> descriptors = descriptorsByDbEntity.get(dbEntity);
 
-                    if (descriptors == null) {
-                        descriptors = new ArrayList<>(1);
-                        dbEntities.add(dbEntity);
-                        descriptorsByDbEntity.put(dbEntity, descriptors);
-                    }
+        if (descriptors == null) {
+            descriptors = new ArrayList<>(1);
+            dbEntities.add(dbEntity);
+            descriptorsByDbEntity.put(dbEntity, descriptors);
+        }
 
-                    if (!containsClassDescriptor(descriptors, descriptor)) {
-                        descriptors.add(dbEntityDescriptor);
-                    }
-                }
-            }
+        if (!containsClassDescriptor(descriptors, descriptor)) {
+            descriptors.add(dbEntityDescriptor);
         }
     }
 
@@ -154,15 +141,7 @@ abstract class DataDomainSyncBucket {
     }
 
     void addDirtyObject(Persistent object, ClassDescriptor descriptor) {
-
-        List<Persistent> objects = objectsByDescriptor.get(descriptor);
-        if (objects == null) {
-
-            objects = new ArrayList<>();
-            objectsByDescriptor.put(descriptor, objects);
-        }
-
-        objects.add(object);
+        objectsByDescriptor.computeIfAbsent(descriptor, k -> new ArrayList<>()).add(object);
     }
 
     void postprocess() {
@@ -243,7 +222,7 @@ abstract class DataDomainSyncBucket {
         }
     }
 
-    private final void remapTarget(
+    private void remapTarget(
             ToManyMapProperty property,
             Object source,
             Object target) throws PropertyException {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/a0b06f45/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainUpdateBucket.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainUpdateBucket.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainUpdateBucket.java
index 59e2f1f..57d871a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainUpdateBucket.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainUpdateBucket.java
@@ -28,14 +28,15 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.map.Attribute;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
 import org.apache.cayenne.query.Query;
 import org.apache.cayenne.query.UpdateBatchQuery;
+import org.apache.cayenne.reflect.ClassDescriptor;
 
 /**
  * @since 1.2
@@ -47,6 +48,17 @@ class DataDomainUpdateBucket extends DataDomainSyncBucket {
     }
 
     @Override
+    void addSpannedDbEntities(ClassDescriptor descriptor) {
+        super.addSpannedDbEntities(descriptor);
+        // for update we need to add entities for flattened toOne relationships
+        for(ObjRelationship objRelationship : descriptor.getEntity().getRelationships()) {
+            if(objRelationship.isFlattened() && !objRelationship.isToMany()) {
+                addDescriptor(descriptor, new DbEntityClassDescriptor(descriptor, objRelationship));
+            }
+        }
+    }
+
+    @Override
     void appendQueriesInternal(Collection<Query> queries) {
 
         DataDomainDBDiffBuilder diffBuilder = new DataDomainDBDiffBuilder();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/a0b06f45/cayenne-server/src/main/java/org/apache/cayenne/access/DbEntityClassDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbEntityClassDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbEntityClassDescriptor.java
index 87954ba..273ce33 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbEntityClassDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbEntityClassDescriptor.java
@@ -18,11 +18,13 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
 import org.apache.cayenne.reflect.ClassDescriptor;
 
 import java.util.ArrayList;
@@ -58,7 +60,7 @@ class DbEntityClassDescriptor {
                 if (object instanceof DbRelationship) {
 
                     if (pathFromMaster == null) {
-                        pathFromMaster = new ArrayList<>(2);
+                        pathFromMaster = new ArrayList<>(1);
                     }
 
                     pathFromMaster.add((DbRelationship) object);
@@ -74,6 +76,17 @@ class DbEntityClassDescriptor {
         }
     }
 
+    DbEntityClassDescriptor(ClassDescriptor classDescriptor, ObjRelationship masterRelationship) {
+        if(masterRelationship.getDbRelationships().size() > 2) {
+            throw new CayenneRuntimeException("Only two step flattened relationships are supported, " + masterRelationship.getDbRelationshipPath());
+        }
+        this.classDescriptor = classDescriptor;
+        DbRelationship pathRelationship = masterRelationship.getDbRelationships().get(0);
+        pathFromMaster = new ArrayList<>(1);
+        pathFromMaster.add(pathRelationship);
+        dbEntity = pathRelationship.getTargetEntity();
+    }
+
     boolean isMaster() {
         return pathFromMaster == null;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/a0b06f45/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 f5da5bb..cbdd8d4 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
@@ -19,6 +19,7 @@
 package org.apache.cayenne.access;
 
 import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.query.EJBQLQuery;
 import org.apache.cayenne.query.ObjectSelect;
@@ -42,6 +43,7 @@ import java.util.Map;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
@@ -54,6 +56,9 @@ public class VerticalInheritanceIT extends ServerCase {
 	@Inject
 	protected DBHelper dbHelper;
 
+	@Inject
+	protected ServerRuntime runtime;
+
     @Test
 	public void testInsert_Root() throws Exception {
 
@@ -237,8 +242,8 @@ public class VerticalInheritanceIT extends ServerCase {
 	public void testUpdateRelation_Sub3() throws Exception {
 		TableHelper ivRootTable = new TableHelper(dbHelper, "IV_ROOT");
 		ivRootTable.setColumns("ID", "NAME", "DISCRIMINATOR");
-		ivRootTable.insert(1, null, null);
-		ivRootTable.insert(2, null, null);
+		ivRootTable.insert(1, "root1", null);
+		ivRootTable.insert(2, "root2", null);
 		ivRootTable.insert(3, "name", "IvSub3");
 
 		TableHelper ivSub3Table = new TableHelper(dbHelper, "IV_SUB3");
@@ -253,6 +258,17 @@ public class VerticalInheritanceIT extends ServerCase {
 		// this will create 3 queries...
 		// update for name, insert for new relationship, delete for old relationship
 		context.commitChanges();
+
+		ObjectContext cleanContext = runtime.newContext();
+		IvSub3 sub3Clean = SelectById.query(IvSub3.class, 3).selectOne(cleanContext);
+
+		assertNotNull(sub3Clean);
+		assertNotSame(sub3, sub3Clean);
+
+		assertEquals("new name", sub3.getName());
+		assertNotNull(sub3Clean.getIvRoot());
+		assertEquals("root2", sub3Clean.getIvRoot().getName());
+
 	}
 
     @Test