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 2022/08/16 08:08:53 UTC

[cayenne] branch master updated: CAY-2754 Add SELF property to the cgen templates

This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git


The following commit(s) were added to refs/heads/master by this push:
     new 72b5a6254 CAY-2754 Add SELF property to the cgen templates
72b5a6254 is described below

commit 72b5a62544fa2d9f80a2620d3a43734b9045bfd6
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Tue Aug 16 11:08:41 2022 +0300

    CAY-2754 Add SELF property to the cgen templates
---
 RELEASE-NOTES.txt                                  |   1 +
 .../java/org/apache/cayenne/gen/PropertyUtils.java |  12 +++
 .../main/resources/templates/v4_1/singleclass.vm   |   7 +-
 .../main/resources/templates/v4_1/superclass.vm    |   6 ++
 .../org/apache/cayenne/access/DataContextIT.java   |   2 +-
 .../cayenne/exp/property/PropertyFactoryTest.java  |   3 +-
 .../org/apache/cayenne/query/ColumnSelectIT.java   | 105 +++++++--------------
 .../cayenne/query/ObjectSelect_SubqueryIT.java     |   9 +-
 .../cayenne/testdo/testmap/auto/_ArtGroup.java     |   3 +-
 .../cayenne/testdo/testmap/auto/_Artist.java       |   5 +-
 .../testdo/testmap/auto/_ArtistCallback.java       |   5 +-
 .../testdo/testmap/auto/_ArtistExhibit.java        |   4 +-
 .../testdo/testmap/auto/_CompoundPainting.java     |   4 +-
 .../testmap/auto/_CompoundPaintingLongNames.java   |   4 +-
 .../cayenne/testdo/testmap/auto/_Exhibit.java      |   4 +-
 .../cayenne/testdo/testmap/auto/_Gallery.java      |   5 +-
 .../auto/_MeaningfulGeneratedColumnTestEntity.java |   5 +-
 .../testdo/testmap/auto/_NullTestEntity.java       |   5 +-
 .../cayenne/testdo/testmap/auto/_Painting.java     |   4 +-
 .../cayenne/testdo/testmap/auto/_Painting1.java    |   4 +-
 .../cayenne/testdo/testmap/auto/_PaintingInfo.java |   4 +-
 .../cayenne/testdo/testmap/auto/_ROArtist.java     |  13 +--
 .../cayenne/testdo/testmap/auto/_ROPainting.java   |   4 +-
 .../testdo/testmap/auto/_RWCompoundPainting.java   |   5 +-
 .../cayenne/testdo/testmap/auto/_SubPainting.java  |   5 +-
 cayenne-server/src/test/resources/testmap.map.xml  |  16 ++++
 26 files changed, 139 insertions(+), 105 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index fc3bb27a9..7458cf8dd 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -22,6 +22,7 @@ CAY-2747 Update project XML version to 11
 CAY-2751 Simplify DataNode configuration
 CAY-2752 Rename queryTemplate to dataMapTemplate in the cgen config
 CAY-2753 Remove VPP support in the ant task
+CAY-2754 Add SELF property to the cgen templates
 
 Bug Fixes:
 
diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/PropertyUtils.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/PropertyUtils.java
index b09f38095..4c4f7782b 100644
--- a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/PropertyUtils.java
+++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/PropertyUtils.java
@@ -128,6 +128,12 @@ public class PropertyUtils {
         }
     }
 
+    public void addImportForSelfProperty(ObjEntity entity) {
+        importUtils.addType(PropertyFactory.class.getName());
+        importUtils.addType(EntityProperty.class.getName());
+        importUtils.addType(entity.getJavaClassName());
+    }
+
     public void addImport(ObjAttribute attribute) throws ClassNotFoundException {
         importUtils.addType(PropertyFactory.class.getName());
         importUtils.addType(attribute.getType());
@@ -162,6 +168,12 @@ public class PropertyUtils {
         }
     }
 
+    public String selfPropertyDefinition(ObjEntity entity) {
+        String propertyType = importUtils.formatJavaType(entity.getJavaClassName());
+        return String.format("public static final EntityProperty<%s> SELF = PropertyFactory.createSelf(%s.class);",
+                propertyType, propertyType);
+    }
+
     public String propertyDefinition(ObjEntity entity, DbAttribute attribute) throws ClassNotFoundException {
         StringUtils utils = StringUtils.getInstance();
 
diff --git a/cayenne-cgen/src/main/resources/templates/v4_1/singleclass.vm b/cayenne-cgen/src/main/resources/templates/v4_1/singleclass.vm
index 460ad614c..7c6dfad3f 100644
--- a/cayenne-cgen/src/main/resources/templates/v4_1/singleclass.vm
+++ b/cayenne-cgen/src/main/resources/templates/v4_1/singleclass.vm
@@ -48,6 +48,7 @@ $propertyUtils.addImport($attr)##
 #foreach( $rel in ${object.DeclaredRelationships} )
 $propertyUtils.addImport($rel)##
 #end
+$propertyUtils.addImportForSelfProperty($object)##
 ${importUtils.generate()}
 
 #set ( $comment = ${metadataUtils.getComment($object)} )
@@ -60,6 +61,11 @@ public#if("true" == "${object.isAbstract()}") abstract#end class ${subClassName}
 
     private static final long serialVersionUID = 1L;
 
+###########################
+## Create self property  ##
+###########################
+    $propertyUtils.selfPropertyDefinition($object)
+
 ###########################
 ## Create property names ##
 ###########################
@@ -78,7 +84,6 @@ public#if("true" == "${object.isAbstract()}") abstract#end class ${subClassName}
 #if( $object.DbEntity )
     #foreach( $idAttr in ${object.DbEntity.PrimaryKeys} )
         #if( $createPKProperties && !${entityUtils.declaresDbAttribute($idAttr)})
-            #set ( $type = "$importUtils.dbAttributeToJavaType($idAttr)")
     $propertyUtils.propertyDefinition($object, $idAttr)
         #else
     public static final String ${stringUtils.capitalizedAsConstant($idAttr.Name)}_PK_COLUMN = "${idAttr.Name}";
diff --git a/cayenne-cgen/src/main/resources/templates/v4_1/superclass.vm b/cayenne-cgen/src/main/resources/templates/v4_1/superclass.vm
index 77c61a9b9..245de0239 100644
--- a/cayenne-cgen/src/main/resources/templates/v4_1/superclass.vm
+++ b/cayenne-cgen/src/main/resources/templates/v4_1/superclass.vm
@@ -50,6 +50,7 @@ $propertyUtils.addImport($attr)##
 #foreach( $rel in ${object.DeclaredRelationships} )
 $propertyUtils.addImport($rel)##
 #end
+$propertyUtils.addImportForSelfProperty($object)##
 ${importUtils.generate()}
 
 /**
@@ -68,6 +69,11 @@ public abstract class ${superClassName} extends ${baseClassName} {
 
     private static final long serialVersionUID = 1L;
 
+###########################
+## Create self property  ##
+###########################
+    $propertyUtils.selfPropertyDefinition($object)
+
 ###########################
 ## Create property names ##
 ###########################
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIT.java
index 4b91c39d6..5191ec563 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIT.java
@@ -553,7 +553,7 @@ public class DataContextIT extends ServerCase {
 
 		Painting painting = context.newObject(Painting.class);
 		painting.setPaintingTitle("paint");
-		a1.addToPaintingArray(painting);
+		a1.addToManyTarget("paintingArray", painting, true);
 
 		assertEquals(PersistenceState.MODIFIED, a1.getPersistenceState());
 		try {
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyFactoryTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyFactoryTest.java
index 2da737d19..74ed1c614 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyFactoryTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyFactoryTest.java
@@ -187,8 +187,7 @@ public class PropertyFactoryTest {
 
     @Test
     public void createSelf() {
-        EntityProperty<Artist> property = PropertyFactory
-                .createSelf(Artist.class);
+        EntityProperty<Artist> property = PropertyFactory.createSelf(Artist.class);
 
         assertNull(property.getName());
         assertEquals(fullObjectExp(), property.getExpression());
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
index d8ff323f6..3111740ae 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
@@ -36,8 +36,6 @@ import org.apache.cayenne.ResultBatchIterator;
 import org.apache.cayenne.access.DataContext;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.NumericProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
@@ -487,12 +485,12 @@ public class ColumnSelectIT extends ServerCase {
         // test that all table aliases are correct
         List<Object[]> result = ObjectSelect.columnQuery(Artist.class,
                 Artist.PAINTING_ARRAY.outer().count(),
-                PropertyFactory.createSelf(Artist.class),
+                Artist.SELF,
                 Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE),
-                PropertyFactory.createSelf(Artist.class),
+                Artist.SELF,
                 Artist.PAINTING_ARRAY.dot(Painting.TO_GALLERY).dot(Gallery.GALLERY_NAME),
                 Artist.ARTIST_NAME,
-                PropertyFactory.createSelf(Artist.class)
+                Artist.SELF
         ).select(context);
         assertEquals(21, result.size());
 
@@ -624,9 +622,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testPageSizeOneObject() {
-        EntityProperty<Artist> artistFull = PropertyFactory.createSelf(Artist.class);
         List<Artist> a = ObjectSelect.query(Artist.class)
-                .column(artistFull)
+                .column(Artist.SELF)
                 .pageSize(10)
                 .select(context);
         assertNotNull(a);
@@ -638,9 +635,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testPageSizeOneObjectAsArray() {
-        EntityProperty<Artist> artistFull = PropertyFactory.createSelf(Artist.class);
         List<Object[]> a = ObjectSelect.query(Artist.class)
-                .columns(artistFull)
+                .columns(Artist.SELF)
                 .pageSize(10)
                 .select(context);
         assertNotNull(a);
@@ -653,9 +649,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testPageSizeObjectAndScalars() {
-        EntityProperty<Artist> artistFull = PropertyFactory.createSelf(Artist.class);
         List<Object[]> a = ObjectSelect.query(Artist.class)
-                .columns(Artist.ARTIST_NAME, artistFull, Artist.PAINTING_ARRAY.count())
+                .columns(Artist.ARTIST_NAME, Artist.SELF, Artist.PAINTING_ARRAY.count())
                 .pageSize(10)
                 .select(context);
         assertNotNull(a);
@@ -672,9 +667,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testPageSizeObjects() {
-        EntityProperty<Artist> artistFull = PropertyFactory.createSelf(Artist.class);
         List<Object[]> a = ObjectSelect.query(Artist.class)
-                .columns(Artist.ARTIST_NAME, artistFull, Artist.PAINTING_ARRAY.flat())
+                .columns(Artist.ARTIST_NAME, Artist.SELF, Artist.PAINTING_ARRAY.flat())
                 .pageSize(10)
                 .select(context);
 
@@ -698,10 +692,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testObjectColumnWithJointPrefetch() {
-        EntityProperty<Artist> artistFull = PropertyFactory.createSelf(Artist.class);
-
         List<Object[]> result = ObjectSelect.query(Artist.class)
-                .columns(artistFull, Artist.DATE_OF_BIRTH, Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE))
+                .columns(Artist.SELF, Artist.DATE_OF_BIRTH, Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE))
                 .prefetch(Artist.PAINTING_ARRAY.joint())
                 .select(context);
 
@@ -710,10 +702,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testObjectColumnWithDisjointPrefetch() {
-        EntityProperty<Artist> artistFull = PropertyFactory.createSelf(Artist.class);
-
         List<Object[]> result = ObjectSelect.query(Artist.class)
-                .columns(artistFull, Artist.DATE_OF_BIRTH, Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE))
+                .columns(Artist.SELF, Artist.DATE_OF_BIRTH, Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE))
                 .prefetch(Artist.PAINTING_ARRAY.disjoint())
                 .select(context);
 
@@ -722,10 +712,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testObjectColumnWithDisjointByIdPrefetch() {
-        EntityProperty<Artist> artistFull = PropertyFactory.createSelf(Artist.class);
-
         List<Object[]> result = ObjectSelect.query(Artist.class)
-                .columns(artistFull, Artist.DATE_OF_BIRTH, Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE))
+                .columns(Artist.SELF, Artist.DATE_OF_BIRTH, Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE))
                 .prefetch(Artist.PAINTING_ARRAY.disjointById())
                 .select(context);
 
@@ -749,10 +737,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testAggregateColumnWithJointPrefetch() {
-        EntityProperty<Artist> artistFull = PropertyFactory.createSelf(Artist.class);
-
         List<Object[]> result = ObjectSelect.query(Artist.class)
-                .columns(artistFull, Artist.PAINTING_ARRAY.count())
+                .columns(Artist.SELF, Artist.PAINTING_ARRAY.count())
                 .prefetch(Artist.PAINTING_ARRAY.joint())
                 .select(context);
 
@@ -761,10 +747,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testAggregateColumnWithDisjointPrefetch() {
-        EntityProperty<Artist> artistFull = PropertyFactory.createSelf(Artist.class);
-
         List<Object[]> result = ObjectSelect.query(Artist.class)
-                .columns(artistFull, Artist.PAINTING_ARRAY.count())
+                .columns(Artist.SELF, Artist.PAINTING_ARRAY.count())
                 .prefetch(Artist.PAINTING_ARRAY.disjoint())
                 .select(context);
 
@@ -773,10 +757,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testAggregateColumnWithDisjointByIdPrefetch() {
-        EntityProperty<Artist> artistFull = PropertyFactory.createSelf(Artist.class);
-
         List<Object[]> result = ObjectSelect.query(Artist.class)
-                .columns(artistFull, Artist.PAINTING_ARRAY.count())
+                .columns(Artist.SELF, Artist.PAINTING_ARRAY.count())
                 .prefetch(Artist.PAINTING_ARRAY.disjointById())
                 .select(context);
 
@@ -800,7 +782,7 @@ public class ColumnSelectIT extends ServerCase {
     @Test
     public void testObjectSelectWithJointPrefetch() {
         List<Artist> result = ObjectSelect.query(Artist.class)
-                .column(PropertyFactory.createSelf(Artist.class))
+                .column(Artist.SELF)
                 .prefetch(Artist.PAINTING_ARRAY.joint())
                 .select(context);
         assertEquals(20, result.size());
@@ -816,7 +798,7 @@ public class ColumnSelectIT extends ServerCase {
     @Test
     public void testObjectWithDisjointPrefetch() {
         List<Artist> result = ObjectSelect.query(Artist.class)
-                .column(PropertyFactory.createSelf(Artist.class))
+                .column(Artist.SELF)
                 .prefetch(Artist.PAINTING_ARRAY.disjoint())
                 .select(context);
         assertEquals(20, result.size());
@@ -831,7 +813,7 @@ public class ColumnSelectIT extends ServerCase {
     @Test
     public void testObjectWithDisjointByIdPrefetch() {
         List<Artist> result = ObjectSelect.query(Artist.class)
-                .column(PropertyFactory.createSelf(Artist.class))
+                .column(Artist.SELF)
                 .prefetch(Artist.PAINTING_ARRAY.disjointById())
                 .select(context);
         assertEquals(20, result.size());
@@ -849,10 +831,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testObjectColumn() {
-        EntityProperty<Artist> artistProperty = PropertyFactory.createSelf(Artist.class);
-
         List<Object[]> result = ObjectSelect.query(Artist.class)
-                .columns(artistProperty, Artist.ARTIST_NAME, Artist.PAINTING_ARRAY.count())
+                .columns(Artist.SELF, Artist.ARTIST_NAME, Artist.PAINTING_ARRAY.count())
                 .select(context);
         assertEquals(5, result.size());
 
@@ -866,11 +846,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testObjectColumnToOne() {
-        EntityProperty<Artist> artistFull = PropertyFactory.createSelf(Painting.TO_ARTIST.getExpression(), Artist.class);
-        EntityProperty<Gallery> galleryFull = PropertyFactory.createSelf(Painting.TO_GALLERY.getExpression(), Gallery.class);
-
         List<Object[]> result = ObjectSelect.query(Painting.class)
-                .columns(Painting.PAINTING_TITLE, artistFull, galleryFull)
+                .columns(Painting.PAINTING_TITLE, Painting.TO_ARTIST, Painting.TO_GALLERY)
                 .select(context);
         assertEquals(21, result.size());
 
@@ -900,10 +877,8 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testObjectColumnToMany() {
-        EntityProperty<Artist> artistProperty = PropertyFactory.createSelf(Artist.class);
-
         List<Object[]> result = ObjectSelect.query(Artist.class)
-                .columns(artistProperty, Artist.PAINTING_ARRAY.flat(), Artist.PAINTING_ARRAY.dot(Painting.TO_GALLERY))
+                .columns(Artist.SELF, Artist.PAINTING_ARRAY.flat(), Artist.PAINTING_ARRAY.dot(Painting.TO_GALLERY))
                 .select(context);
         assertEquals(21, result.size());
 
@@ -931,10 +906,9 @@ public class ColumnSelectIT extends ServerCase {
 
     @Test
     public void testSelfPropertyInOrderBy() {
-        EntityProperty<Artist> artistProperty = PropertyFactory.createSelf(Artist.class);
         List<Artist> artists = ObjectSelect.query(Artist.class)
-                .column(artistProperty)
-                .orderBy(artistProperty.desc())
+                .column(Artist.SELF)
+                .orderBy(Artist.SELF.desc())
                 .select(context);
         assertEquals(20, artists.size());
         assertEquals("artist20", artists.get(0).getArtistName());
@@ -944,11 +918,10 @@ public class ColumnSelectIT extends ServerCase {
     @Test
     public void testSelfPropertyInWhere() {
         Artist artist = ObjectSelect.query(Artist.class).selectFirst(context);
-        EntityProperty<Artist> artistProperty = PropertyFactory.createSelf(Artist.class);
         Artist selectedArtist = ObjectSelect.query(Artist.class)
-                .column(artistProperty)
-                .where(artistProperty.eq(artist))
-                .orderBy(artistProperty.asc())
+                .column(Artist.SELF)
+                .where(Artist.SELF.eq(artist))
+                .orderBy(Artist.SELF.asc())
                 .selectOne(context);
         assertNotNull(selectedArtist);
         assertEquals(artist.getArtistName(), selectedArtist.getArtistName());
@@ -958,9 +931,8 @@ public class ColumnSelectIT extends ServerCase {
     public void testObjPropertyInWhere() {
         Artist artist = ObjectSelect.query(Artist.class, Artist.ARTIST_NAME.eq("artist1"))
                 .selectFirst(context);
-        EntityProperty<Painting> paintingProperty = PropertyFactory.createSelf(Painting.class);
         List<Painting> result = ObjectSelect.query(Painting.class)
-                .column(paintingProperty)
+                .column(Painting.SELF)
                 .where(Painting.TO_ARTIST.eq(artist))
                 .select(context);
         assertEquals(4, result.size());
@@ -1038,9 +1010,7 @@ public class ColumnSelectIT extends ServerCase {
     @Test
     public void testNestedContextObjectResult() {
         ObjectContext childContext = runtime.newContext(context);
-
-        EntityProperty<Artist> artistProperty = PropertyFactory.createSelf(Artist.class);
-        List<Artist> artists = ObjectSelect.columnQuery(Artist.class, artistProperty)
+        List<Artist> artists = ObjectSelect.columnQuery(Artist.class, Artist.SELF)
                 .select(childContext);
         assertEquals(20, artists.size());
         for(Artist artist : artists) {
@@ -1065,8 +1035,7 @@ public class ColumnSelectIT extends ServerCase {
     public void testNestedContextMixedResult() {
         ObjectContext childContext = runtime.newContext(context);
 
-        EntityProperty<Artist> artistProperty = PropertyFactory.createSelf(Artist.class);
-        List<Object[]> data = ObjectSelect.columnQuery(Artist.class, Artist.ARTIST_NAME, artistProperty)
+        List<Object[]> data = ObjectSelect.columnQuery(Artist.class, Artist.ARTIST_NAME, Artist.SELF)
                 .select(childContext);
         assertEquals(20, data.size());
         for(Object[] next : data) {
@@ -1108,17 +1077,14 @@ public class ColumnSelectIT extends ServerCase {
     @Test
     public void test2PkSelect() {
         List<Object[]> results = ObjectSelect.columnQuery(Artist.class,
-                PropertyFactory.createSelf(Artist.class),
-                PropertyFactory
-                        .createBase(ExpressionFactory
-                                .dbPathExp("paintingArray.toArtist.ARTIST_ID"),
-                                Integer.class))
+                        Artist.SELF,
+                        Artist.PAINTING_ARRAY.dot(Painting.TO_ARTIST).dot(Artist.ARTIST_ID_PK_PROPERTY))
                 .where(Artist.ARTIST_ID_PK_PROPERTY.eq(1L))
                 .pageSize(1)
                 .select(context);
         assertEquals(1, results.size());
         assertEquals("artist1", ((Artist)results.get(0)[0]).getArtistName());
-        assertEquals(1, results.get(0)[1]);
+        assertEquals(1L, results.get(0)[1]);
     }
 
     @Test
@@ -1138,19 +1104,16 @@ public class ColumnSelectIT extends ServerCase {
         context.commitChanges();
 
         List<Object[]> results = ObjectSelect.columnQuery(Artist.class,
-                Artist.ARTIST_NAME,
-                PropertyFactory.createSelf(Artist.class),
-                PropertyFactory
-                        .createBase(ExpressionFactory
-                                        .dbPathExp("artistExhibitArray.ARTIST_ID"),
-                                Integer.class))
+                        Artist.ARTIST_NAME,
+                        Artist.SELF,
+                        Artist.ARTIST_EXHIBIT_ARRAY.dot(ArtistExhibit.ARTIST_ID_PK_PROPERTY))
                 .where(Artist.ARTIST_ID_PK_PROPERTY.eq(1L))
                 .pageSize(1)
                 .select(context);
         assertEquals(1, results.size());
         assertEquals("artist1", results.get(0)[0]);
         assertEquals("artist1", ((Artist)results.get(0)[1]).getArtistName());
-        assertEquals(1, results.get(0)[2]);
+        assertEquals(1L, results.get(0)[2]);
     }
 
     @Test
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_SubqueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_SubqueryIT.java
index 64904d589..5741dee42 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_SubqueryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_SubqueryIT.java
@@ -25,7 +25,6 @@ import org.apache.cayenne.access.DataContext;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 import org.apache.cayenne.testdo.testmap.Artist;
@@ -116,11 +115,11 @@ public class ObjectSelect_SubqueryIT extends ServerCase {
     @Test
     public void selectQuery_twoLevelExistsWithExpressionFromParentQuery() {
         Expression deepNestedExp = Artist.ARTIST_NAME.enclosing().enclosing().like("art%")
-                .andExp(Painting.TO_GALLERY.enclosing().eq(PropertyFactory.createSelf(Gallery.class)));
+                .andExp(Painting.TO_GALLERY.enclosing().eq(Gallery.SELF));
 
         Expression exp = Painting.PAINTING_TITLE.like("painting%")
                 .andExp(ExpressionFactory.exists(ObjectSelect.query(Gallery.class, deepNestedExp)))
-                .andExp(Painting.TO_ARTIST.eq(PropertyFactory.createSelf(Artist.class).enclosing()));
+                .andExp(Painting.TO_ARTIST.eq(Artist.SELF.enclosing()));
 
         long count = ObjectSelect.query(Artist.class)
                 .where(ExpressionFactory.exists(ObjectSelect.query(Painting.class, exp)))
@@ -132,11 +131,11 @@ public class ObjectSelect_SubqueryIT extends ServerCase {
     public void objectSelect_twoLevelExistsWithExpressionFromParentQuery() {
         ObjectSelect<Gallery> deepSubquery = ObjectSelect.query(Gallery.class)
                 .where(Artist.ARTIST_NAME.enclosing().enclosing().like("art%"))
-                .and(Painting.TO_GALLERY.enclosing().eq(PropertyFactory.createSelf(Gallery.class)));
+                .and(Painting.TO_GALLERY.enclosing().eq(Gallery.SELF));
 
         ObjectSelect<Painting> subquery = ObjectSelect.query(Painting.class)
                 .where(Painting.PAINTING_TITLE.like("painting%"))
-                .and(Painting.TO_ARTIST.eq(PropertyFactory.createSelf(Artist.class).enclosing()))
+                .and(Painting.TO_ARTIST.eq(Artist.SELF.enclosing()))
                 .and(ExpressionFactory.exists(deepSubquery));
 
         long count = ObjectSelect.query(Artist.class)
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtGroup.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtGroup.java
index b112745c4..3ed21811d 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtGroup.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtGroup.java
@@ -22,8 +22,9 @@ import org.apache.cayenne.testdo.testmap.Artist;
  */
 public abstract class _ArtGroup extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<ArtGroup> SELF = PropertyFactory.createSelf(ArtGroup.class);
     public static final NumericIdProperty<Integer> GROUP_ID_PK_PROPERTY = PropertyFactory.createNumericId("GROUP_ID", "ArtGroup", Integer.class);
     public static final String GROUP_ID_PK_COLUMN = "GROUP_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Artist.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Artist.java
index 8474a2270..520382bc0 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Artist.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Artist.java
@@ -8,11 +8,13 @@ import java.util.List;
 
 import org.apache.cayenne.BaseDataObject;
 import org.apache.cayenne.exp.property.DateProperty;
+import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.ListProperty;
 import org.apache.cayenne.exp.property.NumericIdProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
 import org.apache.cayenne.testdo.testmap.ArtGroup;
+import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.testdo.testmap.ArtistExhibit;
 import org.apache.cayenne.testdo.testmap.Painting;
 
@@ -27,8 +29,9 @@ import org.apache.cayenne.testdo.testmap.Painting;
  */
 public abstract class _Artist extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<Artist> SELF = PropertyFactory.createSelf(Artist.class);
     public static final NumericIdProperty<Long> ARTIST_ID_PK_PROPERTY = PropertyFactory.createNumericId("ARTIST_ID", "Artist", Long.class);
     public static final String ARTIST_ID_PK_COLUMN = "ARTIST_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtistCallback.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtistCallback.java
index ad2f1f621..352b9b34d 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtistCallback.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtistCallback.java
@@ -7,9 +7,11 @@ import java.util.Date;
 
 import org.apache.cayenne.BaseDataObject;
 import org.apache.cayenne.exp.property.DateProperty;
+import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.NumericIdProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
+import org.apache.cayenne.testdo.testmap.ArtistCallback;
 
 /**
  * Class _ArtistCallback was generated by Cayenne.
@@ -19,8 +21,9 @@ import org.apache.cayenne.exp.property.StringProperty;
  */
 public abstract class _ArtistCallback extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<ArtistCallback> SELF = PropertyFactory.createSelf(ArtistCallback.class);
     public static final NumericIdProperty<Integer> ARTIST_ID_PK_PROPERTY = PropertyFactory.createNumericId("ARTIST_ID", "ArtistCallback", Integer.class);
     public static final String ARTIST_ID_PK_COLUMN = "ARTIST_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtistExhibit.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtistExhibit.java
index 6b7cd0bef..da6255046 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtistExhibit.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ArtistExhibit.java
@@ -9,6 +9,7 @@ import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.NumericIdProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.ArtistExhibit;
 import org.apache.cayenne.testdo.testmap.Exhibit;
 
 /**
@@ -19,8 +20,9 @@ import org.apache.cayenne.testdo.testmap.Exhibit;
  */
 public abstract class _ArtistExhibit extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<ArtistExhibit> SELF = PropertyFactory.createSelf(ArtistExhibit.class);
     public static final NumericIdProperty<Long> ARTIST_ID_PK_PROPERTY = PropertyFactory.createNumericId("ARTIST_ID", "ArtistExhibit", Long.class);
     public static final String ARTIST_ID_PK_COLUMN = "ARTIST_ID";
     public static final NumericIdProperty<Integer> EXHIBIT_ID_PK_PROPERTY = PropertyFactory.createNumericId("EXHIBIT_ID", "ArtistExhibit", Integer.class);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_CompoundPainting.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_CompoundPainting.java
index 56c8096dd..b8222b1a1 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_CompoundPainting.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_CompoundPainting.java
@@ -12,6 +12,7 @@ import org.apache.cayenne.exp.property.NumericProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
 import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.CompoundPainting;
 import org.apache.cayenne.testdo.testmap.Gallery;
 import org.apache.cayenne.testdo.testmap.PaintingInfo;
 
@@ -23,8 +24,9 @@ import org.apache.cayenne.testdo.testmap.PaintingInfo;
  */
 public abstract class _CompoundPainting extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<CompoundPainting> SELF = PropertyFactory.createSelf(CompoundPainting.class);
     public static final NumericIdProperty<Integer> PAINTING_ID_PK_PROPERTY = PropertyFactory.createNumericId("PAINTING_ID", "CompoundPainting", Integer.class);
     public static final String PAINTING_ID_PK_COLUMN = "PAINTING_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_CompoundPaintingLongNames.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_CompoundPaintingLongNames.java
index 6d4297aff..dfefc51ea 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_CompoundPaintingLongNames.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_CompoundPaintingLongNames.java
@@ -12,6 +12,7 @@ import org.apache.cayenne.exp.property.NumericProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
 import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.CompoundPaintingLongNames;
 import org.apache.cayenne.testdo.testmap.Gallery;
 import org.apache.cayenne.testdo.testmap.PaintingInfo;
 import org.apache.cayenne.testdo.testmap.ROArtist;
@@ -24,8 +25,9 @@ import org.apache.cayenne.testdo.testmap.ROArtist;
  */
 public abstract class _CompoundPaintingLongNames extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<CompoundPaintingLongNames> SELF = PropertyFactory.createSelf(CompoundPaintingLongNames.class);
     public static final NumericIdProperty<Integer> PAINTING_ID_PK_PROPERTY = PropertyFactory.createNumericId("PAINTING_ID", "CompoundPaintingLongNames", Integer.class);
     public static final String PAINTING_ID_PK_COLUMN = "PAINTING_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Exhibit.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Exhibit.java
index 28954556d..81dc145d3 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Exhibit.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Exhibit.java
@@ -13,6 +13,7 @@ import org.apache.cayenne.exp.property.ListProperty;
 import org.apache.cayenne.exp.property.NumericIdProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.testdo.testmap.ArtistExhibit;
+import org.apache.cayenne.testdo.testmap.Exhibit;
 import org.apache.cayenne.testdo.testmap.Gallery;
 
 /**
@@ -23,8 +24,9 @@ import org.apache.cayenne.testdo.testmap.Gallery;
  */
 public abstract class _Exhibit extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<Exhibit> SELF = PropertyFactory.createSelf(Exhibit.class);
     public static final NumericIdProperty<Integer> EXHIBIT_ID_PK_PROPERTY = PropertyFactory.createNumericId("EXHIBIT_ID", "Exhibit", Integer.class);
     public static final String EXHIBIT_ID_PK_COLUMN = "EXHIBIT_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Gallery.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Gallery.java
index 85c01e0f5..83377c295 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Gallery.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Gallery.java
@@ -6,11 +6,13 @@ import java.io.ObjectOutputStream;
 import java.util.List;
 
 import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.ListProperty;
 import org.apache.cayenne.exp.property.NumericIdProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
 import org.apache.cayenne.testdo.testmap.Exhibit;
+import org.apache.cayenne.testdo.testmap.Gallery;
 import org.apache.cayenne.testdo.testmap.Painting;
 
 /**
@@ -21,8 +23,9 @@ import org.apache.cayenne.testdo.testmap.Painting;
  */
 public abstract class _Gallery extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<Gallery> SELF = PropertyFactory.createSelf(Gallery.class);
     public static final NumericIdProperty<Integer> GALLERY_ID_PK_PROPERTY = PropertyFactory.createNumericId("GALLERY_ID", "Gallery", Integer.class);
     public static final String GALLERY_ID_PK_COLUMN = "GALLERY_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_MeaningfulGeneratedColumnTestEntity.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_MeaningfulGeneratedColumnTestEntity.java
index f71a023af..8be00d782 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_MeaningfulGeneratedColumnTestEntity.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_MeaningfulGeneratedColumnTestEntity.java
@@ -5,9 +5,11 @@ import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
 import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.NumericProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
+import org.apache.cayenne.testdo.testmap.MeaningfulGeneratedColumnTestEntity;
 
 /**
  * Class _MeaningfulGeneratedColumnTestEntity was generated by Cayenne.
@@ -17,8 +19,9 @@ import org.apache.cayenne.exp.property.StringProperty;
  */
 public abstract class _MeaningfulGeneratedColumnTestEntity extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<MeaningfulGeneratedColumnTestEntity> SELF = PropertyFactory.createSelf(MeaningfulGeneratedColumnTestEntity.class);
     public static final String GENERATED_COLUMN_PK_COLUMN = "GENERATED_COLUMN";
 
     public static final NumericProperty<Integer> GENERATED_COLUMN = PropertyFactory.createNumeric("generatedColumn", Integer.class);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_NullTestEntity.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_NullTestEntity.java
index 396758c21..4271a91f4 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_NullTestEntity.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_NullTestEntity.java
@@ -5,9 +5,11 @@ import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
 import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.NumericIdProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
+import org.apache.cayenne.testdo.testmap.NullTestEntity;
 
 /**
  * Class _NullTestEntity was generated by Cayenne.
@@ -17,8 +19,9 @@ import org.apache.cayenne.exp.property.StringProperty;
  */
 public abstract class _NullTestEntity extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<NullTestEntity> SELF = PropertyFactory.createSelf(NullTestEntity.class);
     public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("ID", "NullTestEntity", Integer.class);
     public static final String ID_PK_COLUMN = "ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Painting.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Painting.java
index 3d42f0c12..9f83398f6 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Painting.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Painting.java
@@ -13,6 +13,7 @@ import org.apache.cayenne.exp.property.StringProperty;
 import org.apache.cayenne.testdo.testmap.ArtDataObject;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.testdo.testmap.Gallery;
+import org.apache.cayenne.testdo.testmap.Painting;
 import org.apache.cayenne.testdo.testmap.PaintingInfo;
 
 /**
@@ -23,8 +24,9 @@ import org.apache.cayenne.testdo.testmap.PaintingInfo;
  */
 public abstract class _Painting extends ArtDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<Painting> SELF = PropertyFactory.createSelf(Painting.class);
     public static final NumericIdProperty<Integer> PAINTING_ID_PK_PROPERTY = PropertyFactory.createNumericId("PAINTING_ID", "Painting", Integer.class);
     public static final String PAINTING_ID_PK_COLUMN = "PAINTING_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Painting1.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Painting1.java
index 6d5125fac..9229c21cd 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Painting1.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_Painting1.java
@@ -12,6 +12,7 @@ import org.apache.cayenne.exp.property.NumericProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
 import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Painting1;
 
 /**
  * Class _Painting1 was generated by Cayenne.
@@ -21,8 +22,9 @@ import org.apache.cayenne.testdo.testmap.Artist;
  */
 public abstract class _Painting1 extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<Painting1> SELF = PropertyFactory.createSelf(Painting1.class);
     public static final NumericIdProperty<Integer> PAINTING_ID_PK_PROPERTY = PropertyFactory.createNumericId("PAINTING_ID", "Painting1", Integer.class);
     public static final String PAINTING_ID_PK_COLUMN = "PAINTING_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_PaintingInfo.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_PaintingInfo.java
index 52451b16d..56edc7d8f 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_PaintingInfo.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_PaintingInfo.java
@@ -11,6 +11,7 @@ import org.apache.cayenne.exp.property.NumericIdProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
 import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.testdo.testmap.PaintingInfo;
 
 /**
  * Class _PaintingInfo was generated by Cayenne.
@@ -20,8 +21,9 @@ import org.apache.cayenne.testdo.testmap.Painting;
  */
 public abstract class _PaintingInfo extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<PaintingInfo> SELF = PropertyFactory.createSelf(PaintingInfo.class);
     public static final NumericIdProperty<Integer> PAINTING_ID_PK_PROPERTY = PropertyFactory.createNumericId("PAINTING_ID", "PaintingInfo", Integer.class);
     public static final String PAINTING_ID_PK_COLUMN = "PAINTING_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ROArtist.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ROArtist.java
index 4bbd30f0c..0303ca128 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ROArtist.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ROArtist.java
@@ -8,11 +8,13 @@ import java.util.List;
 
 import org.apache.cayenne.BaseDataObject;
 import org.apache.cayenne.exp.property.DateProperty;
+import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.ListProperty;
 import org.apache.cayenne.exp.property.NumericIdProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
 import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.testdo.testmap.ROArtist;
 
 /**
  * Class _ROArtist was generated by Cayenne.
@@ -22,8 +24,9 @@ import org.apache.cayenne.testdo.testmap.Painting;
  */
 public abstract class _ROArtist extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<ROArtist> SELF = PropertyFactory.createSelf(ROArtist.class);
     public static final NumericIdProperty<Long> ARTIST_ID_PK_PROPERTY = PropertyFactory.createNumericId("ARTIST_ID", "ROArtist", Long.class);
     public static final String ARTIST_ID_PK_COLUMN = "ARTIST_ID";
 
@@ -46,14 +49,6 @@ public abstract class _ROArtist extends BaseDataObject {
         return this.dateOfBirth;
     }
 
-    public void addToPaintingArray(Painting obj) {
-        addToManyTarget("paintingArray", obj, true);
-    }
-
-    public void removeFromPaintingArray(Painting obj) {
-        removeToManyTarget("paintingArray", obj, true);
-    }
-
     @SuppressWarnings("unchecked")
     public List<Painting> getPaintingArray() {
         return (List<Painting>)readProperty("paintingArray");
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ROPainting.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ROPainting.java
index f8f612e85..797727e3f 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ROPainting.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_ROPainting.java
@@ -12,6 +12,7 @@ import org.apache.cayenne.exp.property.NumericProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
 import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.ROPainting;
 
 /**
  * Class _ROPainting was generated by Cayenne.
@@ -21,8 +22,9 @@ import org.apache.cayenne.testdo.testmap.Artist;
  */
 public abstract class _ROPainting extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<ROPainting> SELF = PropertyFactory.createSelf(ROPainting.class);
     public static final NumericIdProperty<Integer> PAINTING_ID_PK_PROPERTY = PropertyFactory.createNumericId("PAINTING_ID", "ROPainting", Integer.class);
     public static final String PAINTING_ID_PK_COLUMN = "PAINTING_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_RWCompoundPainting.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_RWCompoundPainting.java
index fb172f394..510001c20 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_RWCompoundPainting.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_RWCompoundPainting.java
@@ -6,10 +6,12 @@ import java.io.ObjectOutputStream;
 import java.math.BigDecimal;
 
 import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.NumericIdProperty;
 import org.apache.cayenne.exp.property.NumericProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
+import org.apache.cayenne.testdo.testmap.RWCompoundPainting;
 
 /**
  * Class _RWCompoundPainting was generated by Cayenne.
@@ -19,8 +21,9 @@ import org.apache.cayenne.exp.property.StringProperty;
  */
 public abstract class _RWCompoundPainting extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<RWCompoundPainting> SELF = PropertyFactory.createSelf(RWCompoundPainting.class);
     public static final NumericIdProperty<Integer> PAINTING_ID_PK_PROPERTY = PropertyFactory.createNumericId("PAINTING_ID", "RWCompoundPainting", Integer.class);
     public static final String PAINTING_ID_PK_COLUMN = "PAINTING_ID";
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_SubPainting.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_SubPainting.java
index fe4f3c4e4..3f97047e6 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_SubPainting.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/auto/_SubPainting.java
@@ -5,9 +5,11 @@ import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
 import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.NumericIdProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
+import org.apache.cayenne.testdo.testmap.SubPainting;
 
 /**
  * Class _SubPainting was generated by Cayenne.
@@ -17,8 +19,9 @@ import org.apache.cayenne.exp.property.StringProperty;
  */
 public abstract class _SubPainting extends BaseDataObject {
 
-    private static final long serialVersionUID = 1L; 
+    private static final long serialVersionUID = 1L;
 
+    public static final EntityProperty<SubPainting> SELF = PropertyFactory.createSelf(SubPainting.class);
     public static final NumericIdProperty<Integer> PAINTING_ID_PK_PROPERTY = PropertyFactory.createNumericId("PAINTING_ID", "SubPainting", Integer.class);
     public static final String PAINTING_ID_PK_COLUMN = "PAINTING_ID";
 
diff --git a/cayenne-server/src/test/resources/testmap.map.xml b/cayenne-server/src/test/resources/testmap.map.xml
index 80ba5fb0a..109aa7431 100644
--- a/cayenne-server/src/test/resources/testmap.map.xml
+++ b/cayenne-server/src/test/resources/testmap.map.xml
@@ -293,4 +293,20 @@ VALUES (#bind($id), #bind($title), #bind($price))]]></sql>
 		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<sql><![CDATA[select * from ARTIST]]></sql>
 	</query>
+	<cgen xmlns="http://cayenne.apache.org/schema/11/cgen">
+		<destDir>../java</destDir>
+		<mode>entity</mode>
+		<template>templates/v4_1/subclass.vm</template>
+		<superTemplate>templates/v4_1/superclass.vm</superTemplate>
+		<embeddableTemplate>templates/v4_1/embeddable-subclass.vm</embeddableTemplate>
+		<embeddableSuperTemplate>templates/v4_1/embeddable-superclass.vm</embeddableSuperTemplate>
+		<dataMapTemplate>templates/v4_1/datamap-subclass.vm</dataMapTemplate>
+		<dataMapSuperTemplate>templates/v4_1/datamap-superclass.vm</dataMapSuperTemplate>
+		<outputPattern>*.java</outputPattern>
+		<makePairs>true</makePairs>
+		<usePkgPath>true</usePkgPath>
+		<overwrite>false</overwrite>
+		<createPropertyNames>false</createPropertyNames>
+		<createPKProperties>true</createPKProperties>
+	</cgen>
 </data-map>