You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by sk...@apache.org on 2016/08/05 13:07:28 UTC

cayenne git commit: CAY-2097 NullPointerException while updating relationships for entities with vertical inheritance

Repository: cayenne
Updated Branches:
  refs/heads/master 8e6ba1940 -> 697f38e51


CAY-2097 NullPointerException while updating relationships for entities with vertical inheritance


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

Branch: refs/heads/master
Commit: 697f38e5127852a144b13e7640787e57ac3ebba1
Parents: 8e6ba19
Author: Savva Kolbachev <s....@gmail.com>
Authored: Fri Aug 5 16:05:53 2016 +0300
Committer: Savva Kolbachev <s....@gmail.com>
Committed: Fri Aug 5 16:05:53 2016 +0300

----------------------------------------------------------------------
 .../cayenne/access/DataDomainDBDiffBuilder.java | 33 ++++++------
 .../cayenne/access/VerticalInheritanceIT.java   | 30 ++++++++---
 .../apache/cayenne/map/ObjRelationshipIT.java   |  2 +-
 .../testdo/inheritance_vertical/IvAbstract.java |  9 ++++
 .../testdo/inheritance_vertical/IvConcrete.java |  9 ++++
 .../inheritance_vertical/auto/_Iv1Root.java     | 15 +++---
 .../inheritance_vertical/auto/_Iv1Sub1.java     |  9 ++--
 .../inheritance_vertical/auto/_Iv2Root.java     |  9 ++--
 .../inheritance_vertical/auto/_Iv2Sub1.java     |  9 ++--
 .../testdo/inheritance_vertical/auto/_Iv2X.java |  2 +
 .../inheritance_vertical/auto/_IvAbstract.java  | 27 ++++++++++
 .../inheritance_vertical/auto/_IvConcrete.java  | 53 ++++++++++++++++++++
 .../inheritance_vertical/auto/_IvRoot.java      | 15 +++---
 .../inheritance_vertical/auto/_IvSub1.java      |  9 ++--
 .../inheritance_vertical/auto/_IvSub1Sub1.java  |  9 ++--
 .../inheritance_vertical/auto/_IvSub2.java      | 15 +++---
 .../test/resources/inheritance-vertical.map.xml | 32 +++++++++++-
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |  1 +
 18 files changed, 226 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainDBDiffBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainDBDiffBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainDBDiffBuilder.java
index c278a78..0562fc2 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainDBDiffBuilder.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainDBDiffBuilder.java
@@ -19,22 +19,16 @@
 
 package org.apache.cayenne.access;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.access.DataDomainSyncBucket.PropagatedValueFactory;
 import org.apache.cayenne.exp.parser.ASTDbPath;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-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.map.*;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
 
 /**
  * Processes object diffs, generating DB diffs. Can be used for both UPDATE and
@@ -97,9 +91,7 @@ class DataDomainDBDiffBuilder implements GraphChangeHandler {
             for (final Map.Entry<Object, Object> entry : currentPropertyDiff.entrySet()) {
                 ObjAttribute attribute = objEntity.getAttribute(entry.getKey().toString());
 
-                // in case of a flattened attribute, ensure that it belongs to
-                // this
-                // bucket...
+                // In case of a flattened attribute, ensure that it belongs to this bucket...
                 DbAttribute dbAttribute = attribute.getDbAttribute();
                 if (dbAttribute.getEntity() == dbEntity) {
                     dbDiff.put(dbAttribute.getName(), entry.getValue());
@@ -123,12 +115,15 @@ class DataDomainDBDiffBuilder implements GraphChangeHandler {
                     dbRelation = relation.getDbRelationships().get(0);
                 }
 
-                ObjectId targetId = (ObjectId) entry.getValue();
-                for (DbJoin join : dbRelation.getJoins()) {
-                    Object value = (targetId != null) ? new PropagatedValueFactory(targetId, join.getTargetName())
-                            : null;
+                // In case of a vertical inheritance, ensure that it belongs to this bucket...
+                if (dbRelation.getSourceEntity() == dbEntity) {
+                    ObjectId targetId = (ObjectId) entry.getValue();
+                    for (DbJoin join : dbRelation.getJoins()) {
+                        Object value = (targetId != null) ? new PropagatedValueFactory(targetId, join.getTargetName())
+                                : null;
 
-                    dbDiff.put(join.getSourceName(), value);
+                        dbDiff.put(join.getSourceName(), value);
+                    }
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/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 89e22a3..d3e3845 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
@@ -23,14 +23,7 @@ import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
-import org.apache.cayenne.testdo.inheritance_vertical.Iv1Root;
-import org.apache.cayenne.testdo.inheritance_vertical.Iv1Sub1;
-import org.apache.cayenne.testdo.inheritance_vertical.Iv2Sub1;
-import org.apache.cayenne.testdo.inheritance_vertical.Iv2X;
-import org.apache.cayenne.testdo.inheritance_vertical.IvRoot;
-import org.apache.cayenne.testdo.inheritance_vertical.IvSub1;
-import org.apache.cayenne.testdo.inheritance_vertical.IvSub1Sub1;
-import org.apache.cayenne.testdo.inheritance_vertical.IvSub2;
+import org.apache.cayenne.testdo.inheritance_vertical.*;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
 import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
@@ -526,4 +519,25 @@ public class VerticalInheritanceIT extends ServerCase {
 		assertEquals(1, sub1Table.getRowCount());
 	}
 
+	@Test
+	public void testUpdateWithRelationshi() {
+		IvConcrete parent1 = context.newObject(IvConcrete.class);
+		parent1.setName("Parent1");
+		context.commitChanges();
+
+		IvConcrete parent2 = context.newObject(IvConcrete.class);
+		parent2.setName("Parent2");
+		context.commitChanges();
+
+		IvConcrete child = context.newObject(IvConcrete.class);
+		child.setName("Child");
+		child.setParent(parent1);
+		context.commitChanges();
+
+		child.setParent(parent2);
+		context.commitChanges();
+
+		assertEquals(parent2, child.getParent());
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/map/ObjRelationshipIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/ObjRelationshipIT.java b/cayenne-server/src/test/java/org/apache/cayenne/map/ObjRelationshipIT.java
index 34da87d..bc8f7a5 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/ObjRelationshipIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/ObjRelationshipIT.java
@@ -429,7 +429,7 @@ public class ObjRelationshipIT extends ServerCase {
         EntityResolver resolver = new EntityResolver(Collections.singleton(dataMap));
 
         ObjEntity iv2Sub1 = resolver.getObjEntity(Iv2Sub1.class);
-        ObjRelationship x = iv2Sub1.getRelationship(Iv2Sub1.X_PROPERTY);
+        ObjRelationship x = iv2Sub1.getRelationship(Iv2Sub1.X.getName());
         assertTrue(x.isFlattened());
         assertFalse(x.isReadOnly());
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/IvAbstract.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/IvAbstract.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/IvAbstract.java
new file mode 100644
index 0000000..2e94558
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/IvAbstract.java
@@ -0,0 +1,9 @@
+package org.apache.cayenne.testdo.inheritance_vertical;
+
+import org.apache.cayenne.testdo.inheritance_vertical.auto._IvAbstract;
+
+public class IvAbstract extends _IvAbstract {
+
+    private static final long serialVersionUID = 1L; 
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/IvConcrete.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/IvConcrete.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/IvConcrete.java
new file mode 100644
index 0000000..1e70f9c
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/IvConcrete.java
@@ -0,0 +1,9 @@
+package org.apache.cayenne.testdo.inheritance_vertical;
+
+import org.apache.cayenne.testdo.inheritance_vertical.auto._IvConcrete;
+
+public class IvConcrete extends _IvConcrete {
+
+    private static final long serialVersionUID = 1L; 
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv1Root.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv1Root.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv1Root.java
index 9c1a0ae..d17dce6 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv1Root.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv1Root.java
@@ -1,6 +1,7 @@
 package org.apache.cayenne.testdo.inheritance_vertical.auto;
 
 import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.exp.Property;
 
 /**
  * Class _Iv1Root was generated by Cayenne.
@@ -10,23 +11,25 @@ import org.apache.cayenne.CayenneDataObject;
  */
 public abstract class _Iv1Root extends CayenneDataObject {
 
-    public static final String DISCRIMINATOR_PROPERTY = "discriminator";
-    public static final String NAME_PROPERTY = "name";
+    private static final long serialVersionUID = 1L; 
 
     public static final String ID_PK_COLUMN = "ID";
 
+    public static final Property<String> DISCRIMINATOR = new Property<String>("discriminator");
+    public static final Property<String> NAME = new Property<String>("name");
+
     public void setDiscriminator(String discriminator) {
-        writeProperty(DISCRIMINATOR_PROPERTY, discriminator);
+        writeProperty("discriminator", discriminator);
     }
     public String getDiscriminator() {
-        return (String)readProperty(DISCRIMINATOR_PROPERTY);
+        return (String)readProperty("discriminator");
     }
 
     public void setName(String name) {
-        writeProperty(NAME_PROPERTY, name);
+        writeProperty("name", name);
     }
     public String getName() {
-        return (String)readProperty(NAME_PROPERTY);
+        return (String)readProperty("name");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv1Sub1.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv1Sub1.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv1Sub1.java
index 5775ef1..7990007 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv1Sub1.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv1Sub1.java
@@ -1,5 +1,6 @@
 package org.apache.cayenne.testdo.inheritance_vertical.auto;
 
+import org.apache.cayenne.exp.Property;
 import org.apache.cayenne.testdo.inheritance_vertical.Iv1Root;
 
 /**
@@ -10,15 +11,17 @@ import org.apache.cayenne.testdo.inheritance_vertical.Iv1Root;
  */
 public abstract class _Iv1Sub1 extends Iv1Root {
 
-    public static final String NAME_PROPERTY = "name";
+    private static final long serialVersionUID = 1L; 
 
     public static final String ID_PK_COLUMN = "ID";
 
+    public static final Property<String> NAME = new Property<String>("name");
+
     public void setName(String name) {
-        writeProperty(NAME_PROPERTY, name);
+        writeProperty("name", name);
     }
     public String getName() {
-        return (String)readProperty(NAME_PROPERTY);
+        return (String)readProperty("name");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2Root.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2Root.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2Root.java
index b343c22..c118504 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2Root.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2Root.java
@@ -1,6 +1,7 @@
 package org.apache.cayenne.testdo.inheritance_vertical.auto;
 
 import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.exp.Property;
 
 /**
  * Class _Iv2Root was generated by Cayenne.
@@ -10,15 +11,17 @@ import org.apache.cayenne.CayenneDataObject;
  */
 public abstract class _Iv2Root extends CayenneDataObject {
 
-    public static final String DISCRIMINATOR_PROPERTY = "discriminator";
+    private static final long serialVersionUID = 1L; 
 
     public static final String ID_PK_COLUMN = "ID";
 
+    public static final Property<String> DISCRIMINATOR = new Property<String>("discriminator");
+
     public void setDiscriminator(String discriminator) {
-        writeProperty(DISCRIMINATOR_PROPERTY, discriminator);
+        writeProperty("discriminator", discriminator);
     }
     public String getDiscriminator() {
-        return (String)readProperty(DISCRIMINATOR_PROPERTY);
+        return (String)readProperty("discriminator");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2Sub1.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2Sub1.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2Sub1.java
index 69f7930..0e2a642 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2Sub1.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2Sub1.java
@@ -1,5 +1,6 @@
 package org.apache.cayenne.testdo.inheritance_vertical.auto;
 
+import org.apache.cayenne.exp.Property;
 import org.apache.cayenne.testdo.inheritance_vertical.Iv2Root;
 import org.apache.cayenne.testdo.inheritance_vertical.Iv2X;
 
@@ -11,16 +12,18 @@ import org.apache.cayenne.testdo.inheritance_vertical.Iv2X;
  */
 public abstract class _Iv2Sub1 extends Iv2Root {
 
-    public static final String X_PROPERTY = "x";
+    private static final long serialVersionUID = 1L; 
 
     public static final String ID_PK_COLUMN = "ID";
 
+    public static final Property<Iv2X> X = new Property<Iv2X>("x");
+
     public void setX(Iv2X x) {
-        setToOneTarget(X_PROPERTY, x, true);
+        setToOneTarget("x", x, true);
     }
 
     public Iv2X getX() {
-        return (Iv2X)readProperty(X_PROPERTY);
+        return (Iv2X)readProperty("x");
     }
 
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2X.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2X.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2X.java
index 1bcbe84..e6b6a57 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2X.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_Iv2X.java
@@ -10,7 +10,9 @@ import org.apache.cayenne.CayenneDataObject;
  */
 public abstract class _Iv2X extends CayenneDataObject {
 
+    private static final long serialVersionUID = 1L; 
 
     public static final String ID_PK_COLUMN = "ID";
 
+
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvAbstract.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvAbstract.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvAbstract.java
new file mode 100644
index 0000000..b22d7f8
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvAbstract.java
@@ -0,0 +1,27 @@
+package org.apache.cayenne.testdo.inheritance_vertical.auto;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.exp.Property;
+
+/**
+ * Class _IvAbstract was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _IvAbstract extends CayenneDataObject {
+
+    private static final long serialVersionUID = 1L; 
+
+    public static final String ID_PK_COLUMN = "ID";
+
+    public static final Property<String> TYPE = new Property<String>("type");
+
+    public void setType(String type) {
+        writeProperty("type", type);
+    }
+    public String getType() {
+        return (String)readProperty("type");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvConcrete.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvConcrete.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvConcrete.java
new file mode 100644
index 0000000..6cdc238
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvConcrete.java
@@ -0,0 +1,53 @@
+package org.apache.cayenne.testdo.inheritance_vertical.auto;
+
+import java.util.List;
+
+import org.apache.cayenne.exp.Property;
+import org.apache.cayenne.testdo.inheritance_vertical.IvAbstract;
+import org.apache.cayenne.testdo.inheritance_vertical.IvConcrete;
+
+/**
+ * Class _IvConcrete was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _IvConcrete extends IvAbstract {
+
+    private static final long serialVersionUID = 1L; 
+
+    public static final String ID_PK_COLUMN = "ID";
+
+    public static final Property<String> NAME = new Property<String>("name");
+    public static final Property<List<IvConcrete>> CHILDREN = new Property<List<IvConcrete>>("children");
+    public static final Property<IvConcrete> PARENT = new Property<IvConcrete>("parent");
+
+    public void setName(String name) {
+        writeProperty("name", name);
+    }
+    public String getName() {
+        return (String)readProperty("name");
+    }
+
+    public void addToChildren(IvConcrete obj) {
+        addToManyTarget("children", obj, true);
+    }
+    public void removeFromChildren(IvConcrete obj) {
+        removeToManyTarget("children", obj, true);
+    }
+    @SuppressWarnings("unchecked")
+    public List<IvConcrete> getChildren() {
+        return (List<IvConcrete>)readProperty("children");
+    }
+
+
+    public void setParent(IvConcrete parent) {
+        setToOneTarget("parent", parent, true);
+    }
+
+    public IvConcrete getParent() {
+        return (IvConcrete)readProperty("parent");
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvRoot.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvRoot.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvRoot.java
index 96cdf07..09b8ceb 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvRoot.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvRoot.java
@@ -1,6 +1,7 @@
 package org.apache.cayenne.testdo.inheritance_vertical.auto;
 
 import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.exp.Property;
 
 /**
  * Class _IvRoot was generated by Cayenne.
@@ -10,23 +11,25 @@ import org.apache.cayenne.CayenneDataObject;
  */
 public abstract class _IvRoot extends CayenneDataObject {
 
-    public static final String DISCRIMINATOR_PROPERTY = "discriminator";
-    public static final String NAME_PROPERTY = "name";
+    private static final long serialVersionUID = 1L; 
 
     public static final String ID_PK_COLUMN = "ID";
 
+    public static final Property<String> DISCRIMINATOR = new Property<String>("discriminator");
+    public static final Property<String> NAME = new Property<String>("name");
+
     public void setDiscriminator(String discriminator) {
-        writeProperty(DISCRIMINATOR_PROPERTY, discriminator);
+        writeProperty("discriminator", discriminator);
     }
     public String getDiscriminator() {
-        return (String)readProperty(DISCRIMINATOR_PROPERTY);
+        return (String)readProperty("discriminator");
     }
 
     public void setName(String name) {
-        writeProperty(NAME_PROPERTY, name);
+        writeProperty("name", name);
     }
     public String getName() {
-        return (String)readProperty(NAME_PROPERTY);
+        return (String)readProperty("name");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub1.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub1.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub1.java
index 17e1222..ff4410b 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub1.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub1.java
@@ -1,5 +1,6 @@
 package org.apache.cayenne.testdo.inheritance_vertical.auto;
 
+import org.apache.cayenne.exp.Property;
 import org.apache.cayenne.testdo.inheritance_vertical.IvRoot;
 
 /**
@@ -10,15 +11,17 @@ import org.apache.cayenne.testdo.inheritance_vertical.IvRoot;
  */
 public abstract class _IvSub1 extends IvRoot {
 
-    public static final String SUB1NAME_PROPERTY = "sub1Name";
+    private static final long serialVersionUID = 1L; 
 
     public static final String ID_PK_COLUMN = "ID";
 
+    public static final Property<String> SUB1NAME = new Property<String>("sub1Name");
+
     public void setSub1Name(String sub1Name) {
-        writeProperty(SUB1NAME_PROPERTY, sub1Name);
+        writeProperty("sub1Name", sub1Name);
     }
     public String getSub1Name() {
-        return (String)readProperty(SUB1NAME_PROPERTY);
+        return (String)readProperty("sub1Name");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub1Sub1.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub1Sub1.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub1Sub1.java
index 9dffcfc..21a8525 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub1Sub1.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub1Sub1.java
@@ -1,5 +1,6 @@
 package org.apache.cayenne.testdo.inheritance_vertical.auto;
 
+import org.apache.cayenne.exp.Property;
 import org.apache.cayenne.testdo.inheritance_vertical.IvSub1;
 
 /**
@@ -10,15 +11,17 @@ import org.apache.cayenne.testdo.inheritance_vertical.IvSub1;
  */
 public abstract class _IvSub1Sub1 extends IvSub1 {
 
-    public static final String SUB1SUB1NAME_PROPERTY = "sub1Sub1Name";
+    private static final long serialVersionUID = 1L; 
 
     public static final String ID_PK_COLUMN = "ID";
 
+    public static final Property<String> SUB1SUB1NAME = new Property<String>("sub1Sub1Name");
+
     public void setSub1Sub1Name(String sub1Sub1Name) {
-        writeProperty(SUB1SUB1NAME_PROPERTY, sub1Sub1Name);
+        writeProperty("sub1Sub1Name", sub1Sub1Name);
     }
     public String getSub1Sub1Name() {
-        return (String)readProperty(SUB1SUB1NAME_PROPERTY);
+        return (String)readProperty("sub1Sub1Name");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub2.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub2.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub2.java
index b222715..88f8e32 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub2.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvSub2.java
@@ -1,5 +1,6 @@
 package org.apache.cayenne.testdo.inheritance_vertical.auto;
 
+import org.apache.cayenne.exp.Property;
 import org.apache.cayenne.testdo.inheritance_vertical.IvRoot;
 
 /**
@@ -10,23 +11,25 @@ import org.apache.cayenne.testdo.inheritance_vertical.IvRoot;
  */
 public abstract class _IvSub2 extends IvRoot {
 
-    public static final String SUB2ATTR_PROPERTY = "sub2Attr";
-    public static final String SUB2NAME_PROPERTY = "sub2Name";
+    private static final long serialVersionUID = 1L; 
 
     public static final String ID_PK_COLUMN = "ID";
 
+    public static final Property<String> SUB2ATTR = new Property<String>("sub2Attr");
+    public static final Property<String> SUB2NAME = new Property<String>("sub2Name");
+
     public void setSub2Attr(String sub2Attr) {
-        writeProperty(SUB2ATTR_PROPERTY, sub2Attr);
+        writeProperty("sub2Attr", sub2Attr);
     }
     public String getSub2Attr() {
-        return (String)readProperty(SUB2ATTR_PROPERTY);
+        return (String)readProperty("sub2Attr");
     }
 
     public void setSub2Name(String sub2Name) {
-        writeProperty(SUB2NAME_PROPERTY, sub2Name);
+        writeProperty("sub2Name", sub2Name);
     }
     public String getSub2Name() {
-        return (String)readProperty(SUB2NAME_PROPERTY);
+        return (String)readProperty("sub2Name");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/cayenne-server/src/test/resources/inheritance-vertical.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/inheritance-vertical.map.xml b/cayenne-server/src/test/resources/inheritance-vertical.map.xml
index 78da56e..1a48639 100644
--- a/cayenne-server/src/test/resources/inheritance-vertical.map.xml
+++ b/cayenne-server/src/test/resources/inheritance-vertical.map.xml
@@ -3,7 +3,7 @@
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	 xsi:schemaLocation="http://cayenne.apache.org/schema/8/modelMap http://cayenne.apache.org/schema/8/modelMap.xsd"
 	 project-version="8">
-	<property name="defaultPackage" value="org.apache.cayenne.testdo.inheritance.vertical"/>
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.inheritance_vertical"/>
 	<db-entity name="IV1_ROOT">
 		<db-attribute name="DISCRIMINATOR" type="VARCHAR" length="10"/>
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
@@ -42,6 +42,22 @@
 		<db-attribute name="SUB2_ATTR" type="VARCHAR" length="100"/>
 		<db-attribute name="SUB2_NAME" type="VARCHAR" length="100"/>
 	</db-entity>
+	<db-entity name="IV_CONCRETE">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+	</db-entity>
+	<db-entity name="IV_ABSTRACT">
+		<db-attribute name="PARENT_ID" type="INTEGER"/>
+		<db-attribute name="TYPE" type="CHAR" isMandatory="true" length="1"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<obj-entity name="IvConcrete" superEntityName="IvAbstract" className="org.apache.cayenne.testdo.inheritance_vertical.IvConcrete">
+		<qualifier><![CDATA[type = "S"]]></qualifier>
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="concrete.NAME"/>
+	</obj-entity>
+	<obj-entity name="IvAbstract" abstract="true" className="org.apache.cayenne.testdo.inheritance_vertical.IvAbstract" dbEntityName="IV_ABSTRACT">
+		<obj-attribute name="type" type="java.lang.String" db-attribute-path="TYPE"/>
+	</obj-entity>
 	<obj-entity name="Iv1Root" className="org.apache.cayenne.testdo.inheritance_vertical.Iv1Root" dbEntityName="IV1_ROOT">
 		<obj-attribute name="discriminator" type="java.lang.String" db-attribute-path="DISCRIMINATOR"/>
 		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
@@ -80,6 +96,18 @@
 		<obj-attribute name="sub2Attr" type="java.lang.String" db-attribute-path="sub2.SUB2_ATTR"/>
 		<obj-attribute name="sub2Name" type="java.lang.String" db-attribute-path="sub2.SUB2_NAME"/>
 	</obj-entity>
+	<db-relationship name="abstract" source="IV_CONCRETE" target="IV_ABSTRACT" toMany="false">
+		<db-attribute-pair source="ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="concrete" source="IV_ABSTRACT" target="IV_CONCRETE" toDependentPK="true" toMany="false">
+		<db-attribute-pair source="ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="parent" source="IV_ABSTRACT" target="IV_ABSTRACT" toMany="false">
+		<db-attribute-pair source="PARENT_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="children" source="IV_ABSTRACT" target="IV_ABSTRACT" toMany="true">
+		<db-attribute-pair source="ID" target="PARENT_ID"/>
+	</db-relationship>
 	<db-relationship name="sub1" source="IV1_ROOT" target="IV1_SUB1" toDependentPK="true" toMany="false">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
@@ -117,4 +145,6 @@
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
 	<obj-relationship name="x" source="Iv2Sub1" target="Iv2X" deleteRule="Nullify" db-relationship-path="sub1.x"/>
+	<obj-relationship name="parent" source="IvConcrete" target="IvConcrete" deleteRule="Nullify" db-relationship-path="parent"/>
+	<obj-relationship name="children" source="IvConcrete" target="IvConcrete" deleteRule="Deny" db-relationship-path="children"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/697f38e5/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index 630206f..bbff246 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -37,6 +37,7 @@ CAY-2084 ObjectIdQuery - no cache access polymorphism
 CAY-2086 SelectById.selectFirst stack overflow
 CAY-2087 PostCommitFilter is confused about changes made by Pre* listeners
 CAY-2089 HTTP connections aren't always closed in new ROP implementation
+CAY-2097 NullPointerException while updating relationships for entities with vertical inheritance
 
 ----------------------------------
 Release: 4.0.M3