You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2016/11/04 14:21:14 UTC

cayenne git commit: CAY-2133 ObjectNameGenerator refactoring - unifying relationship name generation

Repository: cayenne
Updated Branches:
  refs/heads/master 2dc30c8a1 -> 21675e4df


CAY-2133 ObjectNameGenerator refactoring - unifying relationship name generation

* getting rid of legacy generator. Can't support it anymore.
* building common obj and db rel name algorithm that works based on a collection of joins


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

Branch: refs/heads/master
Commit: 21675e4df8520ce9785c199f1e350e63fb48778a
Parents: 2dc30c8
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Fri Nov 4 16:07:20 2016 +0300
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Fri Nov 4 17:20:48 2016 +0300

----------------------------------------------------------------------
 .../dbsync/merge/EntityMergeSupport.java        |  2 +-
 .../naming/DefaultObjectNameGenerator.java      | 69 +++++++++++----
 .../naming/LegacyObjectNameGenerator.java       | 58 -------------
 .../dbsync/naming/ObjectNameGenerator.java      | 18 ++--
 .../cayenne/dbsync/reverse/db/DbLoader.java     | 19 ++--
 .../cayenne/dbsync/reverse/db/ExportedKey.java  |  4 +-
 .../dbsync/merge/EntityMergeSupportIT.java      | 15 ++--
 .../naming/DefaultObjectNameGeneratorTest.java  | 91 +++++++++++---------
 .../naming/LegacyObjectNameGeneratorTest.java   | 55 ------------
 .../dbimport/ManyToManyCandidateEntity.java     | 12 +--
 .../dbimport/ManyToManyCandidateEntityTest.java |  4 +-
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |  1 +
 docs/doc/src/main/resources/UPGRADE.txt         |  4 +
 .../InferRelationshipsControllerBase.java       | 60 +++++++------
 .../dialog/objentity/ObjRelationshipInfo.java   | 21 ++---
 .../modeler/util/NameGeneratorPreferences.java  | 10 +--
 .../tools/dbimport/testOneToOne.map.xml-result  |  4 +-
 17 files changed, 184 insertions(+), 263 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java
index aaf96a9..c7b3b2a 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java
@@ -178,7 +178,7 @@ public class EntityMergeSupport {
     private boolean createObjRelationship(ObjEntity entity, DbRelationship dr, String targetEntityName) {
         ObjRelationship or = new ObjRelationship();
         or.setName(NameBuilder.builder(or, entity)
-                .baseName(nameGenerator.objRelationshipName(dr))
+                .baseName(nameGenerator.relationshipName(dr))
                 .name());
 
         or.addDbRelationship(dr);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DefaultObjectNameGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DefaultObjectNameGenerator.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DefaultObjectNameGenerator.java
index 7810222..5f98252 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DefaultObjectNameGenerator.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DefaultObjectNameGenerator.java
@@ -18,14 +18,16 @@
  ****************************************************************/
 package org.apache.cayenne.dbsync.naming;
 
-import org.apache.cayenne.dbsync.reverse.db.ExportedKey;
 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.util.Util;
 import org.jvnet.inflector.Noun;
 
+import java.util.List;
 import java.util.Locale;
+import java.util.Objects;
 
 /**
  * The default strategy for converting DB-layer to Object-layer names.
@@ -36,37 +38,73 @@ public class DefaultObjectNameGenerator implements ObjectNameGenerator {
 
 
     @Override
-    public String dbRelationshipName(ExportedKey key, boolean toMany) {
-        String name = toMany ? toManyRelationshipName(key) : toOneRelationshipName(key);
+    public String relationshipName(DbRelationship... relationshipChain) {
+
+        if (relationshipChain == null || relationshipChain.length < 1) {
+            throw new IllegalArgumentException("At least on relationship is expected: " + relationshipChain);
+        }
+
+        // ignore the name of DbRelationship itself (FWIW we may be generating a new name for it here)...
+        // generate the name based on join semantics...
+
+        String name = isToMany(relationshipChain)
+                ? toManyRelationshipName(relationshipChain)
+                : toOneRelationshipName(relationshipChain);
+
         return Util.underscoredToJava(name, false);
     }
 
-    protected String toManyRelationshipName(ExportedKey key) {
+    protected boolean isToMany(DbRelationship... relationshipChain) {
+
+        for(DbRelationship r : relationshipChain) {
+            if(r.isToMany()) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    protected String toManyRelationshipName(DbRelationship... relationshipChain) {
+
+        DbRelationship last = relationshipChain[relationshipChain.length - 1];
+
         try {
             // by default we use English rules here...
-            return Noun.pluralOf(key.getFKTableName().toLowerCase(), Locale.ENGLISH);
+            return Noun.pluralOf(last.getTargetEntityName().toLowerCase(), Locale.ENGLISH);
         } catch (Exception inflectorError) {
             //  seems that Inflector cannot be trusted. For instance, it
             // throws an exception when invoked for word "ADDRESS" (although
             // lower case works fine). To feel safe, we use superclass'
             // behavior if something's gone wrong
-            return key.getFKTableName();
+            return last.getTargetEntityName();
         }
     }
 
-    protected String toOneRelationshipName(ExportedKey key) {
-        String fkColName = key.getFKColumnName();
+    protected String toOneRelationshipName(DbRelationship... relationshipChain) {
 
-        if (fkColName == null) {
-            return key.getPKTableName();
+        DbRelationship first = relationshipChain[0];
+        DbRelationship last = relationshipChain[relationshipChain.length - 1];
+
+        List<DbJoin> joins = first.getJoins();
+        if (joins.isEmpty()) {
+            throw new IllegalArgumentException("No joins for relationship. Can't generate a name");
         }
-        // trim "ID" in the end
-        else if (fkColName.toUpperCase().endsWith("_ID") && fkColName.length() > 3) {
+
+        DbJoin join1 = joins.get(0);
+
+        // TODO: multi-join relationships
+
+        // return the name of the FK column sans ID
+        String fkColName = join1.getSourceName();
+        if (fkColName == null) {
+            return Objects.requireNonNull(last.getTargetEntityName());
+        } else if (fkColName.toUpperCase().endsWith("_ID") && fkColName.length() > 3) {
             return fkColName.substring(0, fkColName.length() - 3);
         } else if (fkColName.toUpperCase().endsWith("ID") && fkColName.length() > 2) {
             return fkColName.substring(0, fkColName.length() - 2);
         } else {
-            return key.getPKTableName();
+            return Objects.requireNonNull(last.getTargetEntityName());
         }
     }
 
@@ -79,9 +117,4 @@ public class DefaultObjectNameGenerator implements ObjectNameGenerator {
     public String objAttributeName(DbAttribute attr) {
         return Util.underscoredToJava(attr.getName(), false);
     }
-
-    @Override
-    public String objRelationshipName(DbRelationship dbRel) {
-        return Util.underscoredToJava(dbRel.getName(), false);
-    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/LegacyObjectNameGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/LegacyObjectNameGenerator.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/LegacyObjectNameGenerator.java
deleted file mode 100644
index cba4c47..0000000
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/LegacyObjectNameGenerator.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.dbsync.naming;
-
-import org.apache.cayenne.dbsync.reverse.db.ExportedKey;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.util.Util;
-
-/**
- * An ObjectNameGenerator that creates names in Cayenne's old-fashioned style. I.e. the same way Cayenne did before 3.0,
- * with relationship "to" prefixes and "Array" suffixes.
- *
- * @since 4.0
- */
-public class LegacyObjectNameGenerator implements ObjectNameGenerator {
-
-    @Override
-    public String dbRelationshipName(
-            ExportedKey key,
-            boolean toMany) {
-
-        String uglyName = (toMany) ? key.getFKTableName() + "_ARRAY" : "to_" + key.getPKTableName();
-        return Util.underscoredToJava(uglyName, false);
-    }
-
-    @Override
-    public String objEntityName(DbEntity dbEntity) {
-        return Util.underscoredToJava(dbEntity.getName(), true);
-    }
-
-    @Override
-    public String objAttributeName(DbAttribute attr) {
-        return Util.underscoredToJava(attr.getName(), false);
-    }
-
-    @Override
-    public String objRelationshipName(DbRelationship dbRel) {
-        return Util.underscoredToJava(dbRel.getName(), false);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/ObjectNameGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/ObjectNameGenerator.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/ObjectNameGenerator.java
index 63c7952..929fb86 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/ObjectNameGenerator.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/ObjectNameGenerator.java
@@ -21,7 +21,6 @@ package org.apache.cayenne.dbsync.naming;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.dbsync.reverse.db.ExportedKey;
 
 /**
  * A strategy for creating names for object layer metadata artifacts based on their DB counterpart naming. Generated
@@ -43,13 +42,16 @@ public interface ObjectNameGenerator {
     String objAttributeName(DbAttribute dbAttribute);
 
     /**
-     * Generates a name for DbRelationship derived from the DB foreign key name.
+     * Generates a String that can be used as a name of an ObjRelationship, derived from join semantics of a chain of
+     * connected DbRelationships. The chain must contain at least one relationship.
+     *
+     * <p>If we are dealing with a flattened
+     * relationship, extra relationships can be passed. They must be in the same order as they will be in a flattened
+     * relationship.
+     *
+     * <p>Generated name can be usually applied to either ObjRelationship or DbRelationship (in which case the chain
+     * must have exactly one parameter).
      */
-    // TODO: the class is called Object* , but here it is generating a DB-layer name... Better naming?
-    String dbRelationshipName(ExportedKey key, boolean toMany);
+    String relationshipName(DbRelationship... relationshipChain);
 
-    /**
-     * Generates a name for ObjRelationship derived from DbRelationship name.
-     */
-    String objRelationshipName(DbRelationship dbRelationship);
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
index ad5f189..65dd871 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
@@ -199,10 +199,6 @@ public class DbLoader {
 
             // forwardRelationship is a reference from table with primary key
             DbRelationship forwardRelationship = new DbRelationship();
-            forwardRelationship.setName(NameBuilder
-                    .builder(forwardRelationship, pkEntity)
-                    .baseName(nameGenerator.dbRelationshipName(key, true))
-                    .name());
 
             forwardRelationship.setSourceEntity(pkEntity);
             forwardRelationship.setTargetEntityName(fkEntity);
@@ -213,10 +209,7 @@ public class DbLoader {
             // TODO: dirty and non-transparent... using DbRelationshipDetected for the benefit of the merge package.
             // This info is available from joins....
             DbRelationshipDetected reverseRelationship = new DbRelationshipDetected();
-            reverseRelationship.setName(NameBuilder
-                    .builder(reverseRelationship, fkEntity)
-                    .baseName(nameGenerator.dbRelationshipName(key, false))
-                    .name());
+
 
             reverseRelationship.setFkName(key.getFKName());
             reverseRelationship.setSourceEntity(fkEntity);
@@ -233,10 +226,16 @@ public class DbLoader {
 
             forwardRelationship.setToMany(!isOneToOne);
 
-            // TODO: can we avoid resetting the name twice? Do we need a placeholder name above?
+            // set relationship names only after their joins are ready ... generator logic is based on relationship
+            // state...
             forwardRelationship.setName(NameBuilder
                     .builder(forwardRelationship, pkEntity)
-                    .baseName(nameGenerator.dbRelationshipName(key, !isOneToOne))
+                    .baseName(nameGenerator.relationshipName(forwardRelationship))
+                    .name());
+
+            reverseRelationship.setName(NameBuilder
+                    .builder(reverseRelationship, fkEntity)
+                    .baseName(nameGenerator.relationshipName(reverseRelationship))
                     .name());
 
             if (delegate.dbRelationshipLoaded(fkEntity, reverseRelationship)) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/ExportedKey.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/ExportedKey.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/ExportedKey.java
index 1dfbdfb..093cbf0 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/ExportedKey.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/ExportedKey.java
@@ -26,12 +26,12 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 
 /**
- * ExportedKey is an representation of relationship between two tables in database. It can be used for creating names
+ * A representation of relationship between two tables in database. It can be used for creating names
  * for relationships.
  *
  * @since 4.0
  */
-public class ExportedKey implements Comparable {
+class ExportedKey implements Comparable {
 
     private final String pkCatalog;
     private final String pkSchema;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java
index 9f6e002..6f25e31 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java
@@ -88,14 +88,17 @@ public class EntityMergeSupportIT extends MergeCase {
 		objEntity2.setDbEntity(dbEntity2);
 		map.addObjEntity(objEntity2);
 
-		assertTrue(new EntityMergeSupport(new DefaultObjectNameGenerator(), NamePatternMatcher.EXCLUDE_ALL, true, true)
-				.synchronizeWithDbEntities(Arrays.asList(objEntity1, objEntity2)));
+		EntityMergeSupport entityMergeSupport = new EntityMergeSupport(new DefaultObjectNameGenerator(),
+				NamePatternMatcher.EXCLUDE_ALL,
+				true,
+				true);
+		assertTrue(entityMergeSupport.synchronizeWithDbEntities(Arrays.asList(objEntity1, objEntity2)));
 		assertNotNull(objEntity1.getAttribute("name"));
-		assertNotNull(objEntity1.getRelationship("rel1To2"));
-		assertNotNull(objEntity2.getRelationship("rel2To1"));
+		assertNotNull(objEntity1.getRelationship("newTable2s"));
+		assertNotNull(objEntity2.getRelationship("newTable"));
 
-		assertEquals(objEntity1.getRelationship("rel1To2").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_MANY);
-		assertEquals(objEntity2.getRelationship("rel2To1").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_ONE);
+		assertEquals(objEntity1.getRelationship("newTable2s").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_MANY);
+		assertEquals(objEntity2.getRelationship("newTable").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_ONE);
 
 		map.removeObjEntity(objEntity2.getName());
 		map.removeObjEntity(objEntity1.getName());

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/DefaultObjectNameGeneratorTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/DefaultObjectNameGeneratorTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/DefaultObjectNameGeneratorTest.java
index 29f1b41..9bf5fee 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/DefaultObjectNameGeneratorTest.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/DefaultObjectNameGeneratorTest.java
@@ -18,9 +18,9 @@
  ****************************************************************/
 package org.apache.cayenne.dbsync.naming;
 
-import org.apache.cayenne.dbsync.reverse.db.ExportedKey;
 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.junit.Test;
 
@@ -31,42 +31,60 @@ public class DefaultObjectNameGeneratorTest {
     private DefaultObjectNameGenerator generator = new DefaultObjectNameGenerator();
 
 
+    private DbRelationship makeRelationship(String srcEntity, String srcKey, String targetEntity, String targetKey,
+                                            boolean toMany) {
+
+        DbRelationship relationship = new DbRelationship();
+        relationship.addJoin(new DbJoin(relationship, srcKey, targetKey));
+        relationship.setToMany(toMany);
+        relationship.setSourceEntity(new DbEntity(srcEntity));
+        relationship.setTargetEntityName(targetEntity);
+
+        return relationship;
+    }
+
     @Test
-    public void testDbRelationshipName_LowerCase_Underscores() {
-
-        ExportedKey key = new ExportedKey("artist", "artist_id", null,
-                "painting", "artist_id", null, (short) 1);
-        assertEquals("artist", generator.dbRelationshipName(key, false));
-        assertEquals("paintings", generator.dbRelationshipName(key, true));
-
-        key = new ExportedKey("person", "person_id", null,
-                "person", "mother_id", null, (short) 1);
-        assertEquals("mother", generator.dbRelationshipName(key, false));
-        assertEquals("people", generator.dbRelationshipName(key, true));
-
-        key = new ExportedKey("person", "person_id", null,
-                "address", "shipping_address_id", null, (short) 1);
-        assertEquals("shippingAddress", generator.dbRelationshipName(key, false));
-        assertEquals("addresses", generator.dbRelationshipName(key, true));
+    public void testRelationshipName_LowerCase_Underscores() {
+
+        DbRelationship r1 = makeRelationship("painting", "artist_id", "artist", "artist_id", false);
+        assertEquals("artist", generator.relationshipName(r1));
+
+        DbRelationship r2 = makeRelationship("artist", "artist_id", "painting", "artist_id", true);
+        assertEquals("paintings", generator.relationshipName(r2));
+
+        DbRelationship r3 = makeRelationship("person", "mother_id", "person", "person_id", false);
+        assertEquals("mother", generator.relationshipName(r3));
+
+        DbRelationship r4 = makeRelationship("person", "person_id", "person", "mother_id", true);
+        assertEquals("people", generator.relationshipName(r4));
+
+        DbRelationship r5 = makeRelationship("person", "shipping_address_id", "address", "id", false);
+        assertEquals("shippingAddress", generator.relationshipName(r5));
+
+        DbRelationship r6 = makeRelationship("person", "id", "address", "person_id", true);
+        assertEquals("addresses", generator.relationshipName(r6));
     }
 
     @Test
-    public void testDbRelationshipName_UpperCase_Underscores() {
-
-        ExportedKey key = new ExportedKey("ARTIST", "ARTIST_ID", null,
-                "PAINTING", "ARTIST_ID", null, (short) 1);
-        assertEquals("artist", generator.dbRelationshipName(key, false));
-        assertEquals("paintings", generator.dbRelationshipName(key, true));
-
-        key = new ExportedKey("PERSON", "PERSON_ID", null,
-                "PERSON", "MOTHER_ID", null, (short) 1);
-        assertEquals("mother", generator.dbRelationshipName(key, false));
-        assertEquals("people", generator.dbRelationshipName(key, true));
-
-        key = new ExportedKey("PERSON", "PERSON_ID", null,
-                "ADDRESS", "SHIPPING_ADDRESS_ID", null, (short) 1);
-        assertEquals("shippingAddress", generator.dbRelationshipName(key, false));
-        assertEquals("addresses", generator.dbRelationshipName(key, true));
+    public void testRelationshipName_UpperCase_Underscores() {
+
+        DbRelationship r1 = makeRelationship("PAINTING", "ARTIST_ID", "ARTIST", "ARTIST_ID", false);
+        assertEquals("artist", generator.relationshipName(r1));
+
+        DbRelationship r2 = makeRelationship("ARTIST", "ARTIST_ID", "PAINTING", "ARTIST_ID", true);
+        assertEquals("paintings", generator.relationshipName(r2));
+
+        DbRelationship r3 = makeRelationship("PERSON", "MOTHER_ID", "PERSON", "PERSON_ID", false);
+        assertEquals("mother", generator.relationshipName(r3));
+
+        DbRelationship r4 = makeRelationship("PERSON", "PERSON_ID", "PERSON", "MOTHER_ID", true);
+        assertEquals("people", generator.relationshipName(r4));
+
+        DbRelationship r5 = makeRelationship("PERSON", "SHIPPING_ADDRESS_ID", "ADDRESS", "ID", false);
+        assertEquals("shippingAddress", generator.relationshipName(r5));
+
+        DbRelationship r6 = makeRelationship("PERSON", "ID", "ADDRESS", "PERSON_ID", true);
+        assertEquals("addresses", generator.relationshipName(r6));
     }
 
     @Test
@@ -80,11 +98,4 @@ public class DefaultObjectNameGeneratorTest {
         assertEquals("name", generator.objAttributeName(new DbAttribute("NAME")));
         assertEquals("artistName", generator.objAttributeName(new DbAttribute("ARTIST_NAME")));
     }
-
-    @Test
-    public void testObjRelationshipName() {
-        assertEquals("mother", generator.objRelationshipName(new DbRelationship("mother")));
-        assertEquals("persons", generator.objRelationshipName(new DbRelationship("persons")));
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/LegacyObjectNameGeneratorTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/LegacyObjectNameGeneratorTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/LegacyObjectNameGeneratorTest.java
deleted file mode 100644
index b1f5619..0000000
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/LegacyObjectNameGeneratorTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.dbsync.naming;
-
-import org.apache.cayenne.dbsync.naming.LegacyObjectNameGenerator;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.dbsync.reverse.db.ExportedKey;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class LegacyObjectNameGeneratorTest {
-
-    @Test
-    public void testStrategy() throws Exception {
-        LegacyObjectNameGenerator strategy = new LegacyObjectNameGenerator();
-        
-        ExportedKey key = new ExportedKey("ARTIST", "ARTIST_ID", null,
-                "PAINTING", "ARTIST_ID", null, (short) 1);
-        assertEquals(strategy.dbRelationshipName(key, false), "toArtist");
-        assertEquals(strategy.dbRelationshipName(key, true), "paintingArray");
-        
-        key = new ExportedKey("PERSON", "PERSON_ID", null,
-                "PERSON", "MOTHER_ID", null, (short) 1);
-        assertEquals(strategy.dbRelationshipName(key, false), "toPerson");
-        assertEquals(strategy.dbRelationshipName(key, true), "personArray");
-        
-        assertEquals(strategy.objEntityName(new DbEntity("ARTIST")), "Artist");
-        assertEquals(strategy.objEntityName(new DbEntity("ARTIST_WORK")), "ArtistWork");
-        
-        assertEquals(strategy.objAttributeName(new DbAttribute("NAME")), "name");
-        assertEquals(strategy.objAttributeName(new DbAttribute("ARTIST_NAME")), "artistName");
-        
-        assertEquals(strategy.objRelationshipName(new DbRelationship("toArtist")), "toArtist");
-        assertEquals(strategy.objRelationshipName(new DbRelationship("paintingArray")), "paintingArray");
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntity.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntity.java
index da658e5..bbb7c68 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntity.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntity.java
@@ -20,7 +20,6 @@ package org.apache.cayenne.tools.dbimport;
 
 import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
-import org.apache.cayenne.dbsync.reverse.db.ExportedKey;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
@@ -102,19 +101,10 @@ class ManyToManyCandidateEntity {
             return;
         }
 
-        ExportedKey key = new ExportedKey(
-                rel1.getSourceEntity().getName(),
-                rel1.getSourceAttributes().iterator().next().getName(),
-                null,
-                rel2.getTargetEntity().getName(),
-                rel2.getTargetAttributes().iterator().next().getName(),
-                null,
-                (short) 1);
-
         ObjRelationship newRelationship = new ObjRelationship();
         newRelationship.setName(NameBuilder
                 .builder(newRelationship, srcEntity)
-                .baseName(nameGenerator.dbRelationshipName(key, true))
+                .baseName(nameGenerator.relationshipName(rel1, rel2))
                 .name());
 
         newRelationship.setSourceEntity(srcEntity);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntityTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntityTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntityTest.java
index a1260f1..b9632f8 100644
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntityTest.java
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntityTest.java
@@ -25,6 +25,7 @@ import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
 import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.XMLDataMapLoader;
+import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.ClassLoaderManager;
@@ -36,7 +37,6 @@ import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.Relationship;
-import org.apache.cayenne.dbsync.naming.LegacyObjectNameGenerator;
 import org.apache.cayenne.resource.URLResource;
 import org.junit.Before;
 import org.junit.Test;
@@ -96,7 +96,7 @@ public class ManyToManyCandidateEntityTest {
     public void testOptimisationForManyToManyEntity() {
         ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
 
-        ManyToManyCandidateEntity.build(manyToManyEntity).optimizeRelationships(new LegacyObjectNameGenerator());
+        ManyToManyCandidateEntity.build(manyToManyEntity).optimizeRelationships(new DefaultObjectNameGenerator());
 
         ObjEntity table1Entity = map.getObjEntity("Table1");
         ObjEntity table2Entity = map.getObjEntity("Table2");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/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 a21e0f9..bc626be 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -38,6 +38,7 @@ CAY-2116 Split schema synchronization code in a separate module
 CAY-2118 cdbimport: drop support for the old style of table filtering
 CAY-2129 Modeler: reengineer dialog improvements
 CAY-2132 Adding SybaseSelectTranslator to support TOP/DISTINCT TOP in limited queries
+CAY-2133 ObjectNameGenerator refactoring - unifying relationship name generation
 
 Bug Fixes:
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/docs/doc/src/main/resources/UPGRADE.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/UPGRADE.txt b/docs/doc/src/main/resources/UPGRADE.txt
index 50e3479..90c3430 100644
--- a/docs/doc/src/main/resources/UPGRADE.txt
+++ b/docs/doc/src/main/resources/UPGRADE.txt
@@ -6,6 +6,10 @@ IMPORTANT: be sure to read all notes for the intermediate releases between your
 -------------------------------------------------------------------------------
 UPGRADING TO 4.0.M4
 
+* Per CAY-2133, LegacyObjectNameGenerator is no longer provided, as it wasn't possible to maintain it in a fully backwards-
+  compatible manner. Embrace the new naming scheme, or provide your own ObjectNameGenerator if you absolutely need the
+  old names.
+
 * Per CAY-2125 we no longer inject SchemaUpdateStrategy directly. Instead SchemaUpgradeStrategyFactory is injected.
   If you have your own modules with SchemaUpdateStrategy injection, it will be ignored. So please review your
   DI code and update it to use SchemaUpgradeStrategyFactory (or likely its subclass).

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/autorelationship/InferRelationshipsControllerBase.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/autorelationship/InferRelationshipsControllerBase.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/autorelationship/InferRelationshipsControllerBase.java
index 8530dfd..fe92faf 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/autorelationship/InferRelationshipsControllerBase.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/autorelationship/InferRelationshipsControllerBase.java
@@ -18,23 +18,22 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.dialog.autorelationship;
 
-import java.awt.Component;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
+import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
 import org.apache.cayenne.map.DataMap;
 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.dbsync.reverse.db.ExportedKey;
-import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
 import org.apache.cayenne.modeler.util.CayenneController;
 import org.apache.commons.collections.Predicate;
 
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
 public class InferRelationshipsControllerBase extends CayenneController {
 
     public static final String SELECTED_PROPERTY = "selected";
@@ -49,18 +48,17 @@ public class InferRelationshipsControllerBase extends CayenneController {
     protected ObjectNameGenerator strategy;
 
     protected transient InferredRelationship currentEntity;
-    protected transient Integer entityNumber;
 
     public InferRelationshipsControllerBase(CayenneController parent, DataMap dataMap) {
         super(parent);
 
         this.dataMap = dataMap;
-        this.entities = new ArrayList<DbEntity>(dataMap.getDbEntities());
-        this.selectedEntities = new HashSet<InferredRelationship>();
+        this.entities = new ArrayList<>(dataMap.getDbEntities());
+        this.selectedEntities = new HashSet<>();
     }
 
     public void setRelationships() {
-        inferredRelationships = new ArrayList<InferredRelationship>();
+        inferredRelationships = new ArrayList<>();
 
         for (DbEntity entity : entities) {
             createRelationships(entity);
@@ -198,29 +196,29 @@ public class InferRelationshipsControllerBase extends CayenneController {
 
     protected void createNames() {
 
-        ExportedKey key = null;
+
         for (InferredRelationship myir : inferredRelationships) {
+
+            DbRelationship localRelationship = new DbRelationship();
+            localRelationship.setToMany(myir.isToMany());
+
             if (myir.getJoinSource().isPrimaryKey()) {
-                key = getExportedKey(myir.getSource().getName(),
-                                     myir.getJoinSource().getName(),
-                                     myir.getTarget().getName(),
-                                     myir.getJoinTarget().getName());
+
+                localRelationship.addJoin(
+                        new DbJoin(localRelationship, myir.getJoinSource().getName(), myir.getJoinTarget().getName())
+                );
+                localRelationship.setSourceEntity(myir.getSource());
+                localRelationship.setTargetEntityName(myir.getTarget().getName());
             } else {
-                key = getExportedKey(myir.getTarget().getName(),
-                                     myir.getJoinTarget().getName(),
-                                     myir.getSource().getName(),
-                                     myir.getJoinSource().getName());
+                localRelationship.addJoin(
+                        new DbJoin(localRelationship, myir.getJoinTarget().getName(), myir.getJoinSource().getName())
+                );
+                localRelationship.setSourceEntity(myir.getTarget());
+                localRelationship.setTargetEntityName(myir.getSource().getName());
             }
-            myir.setName(strategy.dbRelationshipName(key, myir.isToMany()));
-        }
-    }
 
-    protected ExportedKey getExportedKey(
-            String pkTable,
-            String pkColumn,
-            String fkTable,
-            String fkColumn) {
-        return new ExportedKey(pkTable, pkColumn, null, fkTable, fkColumn, null, (short) 1);
+            myir.setName(strategy.relationshipName(localRelationship));
+        }
     }
 
     public List<InferredRelationship> getSelectedEntities() {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ObjRelationshipInfo.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ObjRelationshipInfo.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ObjRelationshipInfo.java
index 56ad7e6..d9af4ae 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ObjRelationshipInfo.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ObjRelationshipInfo.java
@@ -19,6 +19,7 @@
 package org.apache.cayenne.modeler.dialog.objentity;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.Entity;
@@ -27,8 +28,6 @@ import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
 import org.apache.cayenne.map.Relationship;
 import org.apache.cayenne.map.event.RelationshipEvent;
-import org.apache.cayenne.dbsync.reverse.db.ExportedKey;
-import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ClassLoadingService;
 import org.apache.cayenne.modeler.ProjectController;
@@ -42,12 +41,11 @@ import org.apache.cayenne.modeler.util.NameGeneratorPreferences;
 import org.apache.cayenne.util.DeleteRuleUpdater;
 import org.apache.cayenne.util.Util;
 
-import javax.swing.JOptionPane;
-import javax.swing.WindowConstants;
+import javax.swing.*;
 import javax.swing.event.TreeSelectionEvent;
 import javax.swing.event.TreeSelectionListener;
 import javax.swing.tree.TreePath;
-import java.awt.Component;
+import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
@@ -339,18 +337,15 @@ public class ObjRelationshipInfo extends CayenneController implements TreeSelect
         }
 
         DbRelationship dbRelationship = new DbRelationship();
+        dbRelationship.setSourceEntity(targetModel.getSource());
+        dbRelationship.setTargetEntityName(targetModel.getTarget());
+        dbRelationship.setToMany(targetModel.isToMany());
+
         dbRelationship.setName(createNamingStrategy(NameGeneratorPreferences
                 .getInstance()
                 .getLastUsedStrategies()
-                .get(0)).dbRelationshipName(
-                new ExportedKey(targetModel.getSource().getName(), null, null,
-                                targetModel.getTarget().getName(), null, null, (short) 1),
-                targetModel.isToMany()));
+                .get(0)).relationshipName(dbRelationship));
 
-        // note: NamedObjectFactory doesn't set source or target, just the name
-        dbRelationship.setSourceEntity(targetModel.getSource());
-        dbRelationship.setTargetEntityName(targetModel.getTarget());
-        dbRelationship.setToMany(targetModel.isToMany());
         targetModel.getSource().addRelationship(dbRelationship);
 
         // TODO: creating relationship outside of ResolveDbRelationshipDialog

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/NameGeneratorPreferences.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/NameGeneratorPreferences.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/NameGeneratorPreferences.java
index 9380e2b..92ed76c 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/NameGeneratorPreferences.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/NameGeneratorPreferences.java
@@ -18,15 +18,14 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.util;
 
-import java.util.Arrays;
-import java.util.Vector;
-import java.util.prefs.Preferences;
-
-import org.apache.cayenne.dbsync.naming.LegacyObjectNameGenerator;
 import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
 import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
 import org.apache.cayenne.modeler.Application;
 
+import java.util.Arrays;
+import java.util.Vector;
+import java.util.prefs.Preferences;
+
 /**
  * Helper class to store/read information about naming strategies have been used
  */
@@ -40,7 +39,6 @@ public class NameGeneratorPreferences {
     private static final Vector<String> PREDEFINED_STRATEGIES = new Vector<String>();
     static {
         PREDEFINED_STRATEGIES.add(DefaultObjectNameGenerator.class.getCanonicalName());
-        PREDEFINED_STRATEGIES.add(LegacyObjectNameGenerator.class.getCanonicalName());
     }
 
     static final NameGeneratorPreferences instance = new NameGeneratorPreferences();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/21675e4d/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
index 7dc3e2f..bdaf9be 100644
--- a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
@@ -45,7 +45,7 @@
 	<db-relationship name="pickSchedules" source="PLAYER" target="PICK_SCHEDULE" toMany="true">
 		<db-attribute-pair source="ID" target="SELECTED_PLAYER_ID"/>
 	</db-relationship>
-	<db-relationship name="player" source="PLAYER" target="PLAYER_INFO" toDependentPK="true" toMany="false">
+	<db-relationship name="playerInfo" source="PLAYER" target="PLAYER_INFO" toDependentPK="true" toMany="false">
 		<db-attribute-pair source="ID" target="PLAYER_ID"/>
 	</db-relationship>
 	<db-relationship name="player" source="PLAYER_INFO" target="PLAYER" toMany="false">
@@ -53,6 +53,6 @@
 	</db-relationship>
 	<obj-relationship name="selectedPlayer" source="PickSchedule" target="Player" deleteRule="Nullify" db-relationship-path="selectedPlayer"/>
 	<obj-relationship name="pickSchedules" source="Player" target="PickSchedule" deleteRule="Deny" db-relationship-path="pickSchedules"/>
-	<obj-relationship name="player" source="Player" target="PlayerInfo" deleteRule="Nullify" db-relationship-path="player"/>
+	<obj-relationship name="playerInfo" source="Player" target="PlayerInfo" deleteRule="Nullify" db-relationship-path="playerInfo"/>
 	<obj-relationship name="player" source="PlayerInfo" target="Player" deleteRule="Nullify" db-relationship-path="player"/>
 </data-map>