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/09/28 15:04:49 UTC
[2/2] cayenne git commit: CAY-2113 cdbimport: Reverse-engineering
reinstates previously ignored columns
CAY-2113 cdbimport: Reverse-engineering reinstates previously ignored columns
* fixing...
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/f7f33b55
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/f7f33b55
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/f7f33b55
Branch: refs/heads/master
Commit: f7f33b5570dc704d88322e2ac08bda677050a174
Parents: d58f722
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Wed Sep 28 16:45:56 2016 +0300
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Wed Sep 28 18:02:35 2016 +0300
----------------------------------------------------------------------
.../cayenne/merge/AbstractToModelToken.java | 7 -
.../apache/cayenne/merge/AddColumnToModel.java | 10 +-
.../cayenne/merge/AddRelationshipToModel.java | 14 +-
.../cayenne/merge/CreateTableToModel.java | 10 +-
.../apache/cayenne/util/EntityMergeSupport.java | 277 +++++++++++--------
docs/doc/src/main/resources/RELEASE-NOTES.txt | 1 +
6 files changed, 186 insertions(+), 133 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java
index e2ca05f..49b680b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java
@@ -23,7 +23,6 @@ import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.util.EntityMergeSupport;
/**
* Common abstract superclass for all {@link MergerToken}s going from the database to the
@@ -47,12 +46,6 @@ public abstract class AbstractToModelToken implements MergerToken {
return MergeDirection.TO_MODEL;
}
- protected void synchronizeWithObjEntity(DbEntity entity) {
- for (ObjEntity objEntity : entity.mappedObjEntities()) {
- new EntityMergeSupport(objEntity.getDataMap()).synchronizeWithDbEntity(objEntity);
- }
- }
-
protected static void remove(ModelMergeDelegate mergerContext, DbRelationship rel, boolean reverse) {
if (rel == null) {
return;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java
index 283241c..9e96928 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java
@@ -40,7 +40,15 @@ public class AddColumnToModel extends AbstractToModelToken.EntityAndColumn {
public void execute(MergerContext mergerContext) {
getEntity().addAttribute(getColumn());
- synchronizeWithObjEntity(getEntity());
+
+ // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
+ // important settings
+
+ EntityMergeSupport entityMergeSupport = new EntityMergeSupport(mergerContext.getDataMap());
+ for(ObjEntity e : getEntity().mappedObjEntities()) {
+ entityMergeSupport.synchronizeOnDbAttributeAdded(e, getColumn());
+ }
+
mergerContext.getModelMergeDelegate().dbAttributeAdded(getColumn());
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java
index 5e05b52..42d7329 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java
@@ -21,8 +21,8 @@ package org.apache.cayenne.merge;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbJoin;
import org.apache.cayenne.map.DbRelationship;
-
-import static org.apache.cayenne.util.Util.join;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.util.EntityMergeSupport;
public class AddRelationshipToModel extends AbstractToModelToken.Entity {
@@ -42,7 +42,15 @@ public class AddRelationshipToModel extends AbstractToModelToken.Entity {
public void execute(MergerContext mergerContext) {
getEntity().addRelationship(rel);
// TODO: add reverse relationship as well if it does not exist
- synchronizeWithObjEntity(getEntity());
+
+ // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
+ // important settings
+
+ EntityMergeSupport entityMergeSupport = new EntityMergeSupport(mergerContext.getDataMap());
+ for(ObjEntity e : getEntity().mappedObjEntities()) {
+ entityMergeSupport.synchronizeOnDbRelationshipAdded(e, rel);
+ }
+
mergerContext.getModelMergeDelegate().dbRelationshipAdded(rel);
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
index 61a266a..cdd6009 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
@@ -22,7 +22,7 @@ import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.naming.NameConverter;
-import org.apache.cayenne.util.Util;
+import org.apache.cayenne.util.EntityMergeSupport;
/**
* A {@link MergerToken} to add a {@link DbEntity} to a {@link DataMap}
@@ -85,8 +85,12 @@ public class CreateTableToModel extends AbstractToModelToken.Entity {
map.addObjEntity(objEntity);
- synchronizeWithObjEntity(getEntity());
-
+ // presumably there are no other ObjEntities pointing to this DbEntity, so syncing just this one...
+
+ // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
+ // important settings
+ new EntityMergeSupport(map).synchronizeWithDbEntity(objEntity);
+
mergerContext.getModelMergeDelegate().dbEntityAdded(getEntity());
mergerContext.getModelMergeDelegate().objEntityAdded(objEntity);
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java b/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
index 5bcccce..7c12600 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
@@ -19,13 +19,6 @@
package org.apache.cayenne.util;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbAttribute;
@@ -36,13 +29,20 @@ import org.apache.cayenne.map.Entity;
import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.map.naming.LegacyNameGenerator;
import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
+import org.apache.cayenne.map.naming.LegacyNameGenerator;
import org.apache.cayenne.map.naming.NameCheckers;
import org.apache.cayenne.map.naming.ObjectNameGenerator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
/**
* Implements methods for entity merging.
*/
@@ -64,20 +64,17 @@ public class EntityMergeSupport {
}
private final DataMap map;
-
- protected boolean removeMeaningfulFKs;
- protected boolean removeMeaningfulPKs;
- protected boolean usePrimitives;
-
/**
* Strategy for choosing names for entities, attributes and relationships
*/
private final ObjectNameGenerator nameGenerator;
-
/**
* Listeners of merge process.
*/
private final List<EntityMergeListener> listeners = new ArrayList<EntityMergeListener>();
+ protected boolean removeMeaningfulFKs;
+ protected boolean removeMeaningfulPKs;
+ protected boolean usePrimitives;
public EntityMergeSupport(DataMap map) {
this(map, new LegacyNameGenerator(), true);
@@ -102,7 +99,7 @@ public class EntityMergeSupport {
/**
* Updates each one of the collection of ObjEntities, adding attributes and
* relationships based on the current state of its DbEntity.
- *
+ *
* @return true if any ObjEntity has changed as a result of synchronization.
* @since 1.2 changed signature to use Collection instead of List.
*/
@@ -134,7 +131,7 @@ public class EntityMergeSupport {
/**
* Updates ObjEntity attributes and relationships based on the current state
* of its DbEntity.
- *
+ *
* @return true if the ObjEntity has changed as a result of synchronization.
*/
public boolean synchronizeWithDbEntity(ObjEntity entity) {
@@ -165,6 +162,32 @@ public class EntityMergeSupport {
return changed;
}
+ /**
+ * @since 4.0
+ */
+ public boolean synchronizeOnDbAttributeAdded(ObjEntity entity, DbAttribute dbAttribute) {
+
+ Collection<DbRelationship> incomingRels = getIncomingRelationships(dbAttribute.getEntity());
+ if (isMissingFromObjEntity(entity, dbAttribute, incomingRels)) {
+ addMissingAttribute(entity, dbAttribute);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @since 4.0
+ */
+ public boolean synchronizeOnDbRelationshipAdded(ObjEntity entity, DbRelationship dbRelationship) {
+
+ if (isMissingFromObjEntity(entity, dbRelationship)) {
+ addMissingRelationship(entity, dbRelationship);
+ }
+
+ return true;
+ }
+
private boolean addMissingRelationships(ObjEntity entity) {
List<DbRelationship> relationshipsToAdd = getRelationshipsToAdd(entity);
if (relationshipsToAdd.isEmpty()) {
@@ -172,26 +195,9 @@ public class EntityMergeSupport {
}
for (DbRelationship dr : relationshipsToAdd) {
- DbEntity targetEntity = dr.getTargetEntity();
-
- Collection<ObjEntity> mappedObjEntities = map.getMappedEntities(targetEntity);
- if (!mappedObjEntities.isEmpty()) {
- for (Entity mappedTarget : mappedObjEntities) {
- createObjRelationship(entity, dr, mappedTarget.getName());
- }
- } else {
- if (targetEntity == null) {
- targetEntity = new DbEntity(dr.getTargetEntityName());
- }
- if (dr.getTargetEntityName() != null) {
- boolean needGeneratedEntity = createObjRelationship(entity, dr, nameGenerator.createObjEntityName(targetEntity));
- if (needGeneratedEntity) {
- LOG.warn("Can't find ObjEntity for " + dr.getTargetEntityName());
- LOG.warn("Db Relationship (" + dr + ") will have GUESSED Obj Relationship reflection. ");
- }
- }
- }
+ addMissingRelationship(entity, dr);
}
+
return true;
}
@@ -237,26 +243,55 @@ public class EntityMergeSupport {
private boolean addMissingAttributes(ObjEntity entity) {
boolean changed = false;
+
for (DbAttribute da : getAttributesToAdd(entity)) {
+ addMissingAttribute(entity, da);
+ changed = true;
+ }
+ return changed;
+ }
- String attrName = DefaultUniqueNameGenerator.generate(NameCheckers.objAttribute, entity,
- nameGenerator.createObjAttributeName(da));
+ private void addMissingRelationship(ObjEntity entity, DbRelationship dbRelationship) {
+ DbEntity targetEntity = dbRelationship.getTargetEntity();
+
+ Collection<ObjEntity> mappedObjEntities = map.getMappedEntities(targetEntity);
+ if (!mappedObjEntities.isEmpty()) {
+ for (Entity mappedTarget : mappedObjEntities) {
+ createObjRelationship(entity, dbRelationship, mappedTarget.getName());
+ }
+ } else {
- String type = TypesMapping.getJavaBySqlType(da.getType());
- if (usePrimitives) {
- String primitive = CLASS_TO_PRIMITIVE.get(type);
- if (primitive != null) {
- type = primitive;
+ if (targetEntity == null) {
+ targetEntity = new DbEntity(dbRelationship.getTargetEntityName());
+ }
+
+ if (dbRelationship.getTargetEntityName() != null) {
+ boolean needGeneratedEntity = createObjRelationship(entity, dbRelationship,
+ nameGenerator.createObjEntityName(targetEntity));
+ if (needGeneratedEntity) {
+ LOG.warn("Can't find ObjEntity for " + dbRelationship.getTargetEntityName());
+ LOG.warn("Db Relationship (" + dbRelationship + ") will have GUESSED Obj Relationship reflection. ");
}
}
+ }
+ }
- ObjAttribute oa = new ObjAttribute(attrName, type, entity);
- oa.setDbAttributePath(da.getName());
- entity.addAttribute(oa);
- fireAttributeAdded(oa);
- changed = true;
+ private void addMissingAttribute(ObjEntity entity, DbAttribute da) {
+ String attrName = DefaultUniqueNameGenerator.generate(NameCheckers.objAttribute, entity,
+ nameGenerator.createObjAttributeName(da));
+
+ String type = TypesMapping.getJavaBySqlType(da.getType());
+ if (usePrimitives) {
+ String primitive = CLASS_TO_PRIMITIVE.get(type);
+ if (primitive != null) {
+ type = primitive;
+ }
}
- return changed;
+
+ ObjAttribute oa = new ObjAttribute(attrName, type, entity);
+ oa.setDbAttributePath(da.getName());
+ entity.addAttribute(oa);
+ fireAttributeAdded(oa);
}
private boolean getRidOfAttributesThatAreNowSrcAttributesForRelationships(ObjEntity entity) {
@@ -275,7 +310,7 @@ public class EntityMergeSupport {
/**
* Returns a list of DbAttributes that are mapped to foreign keys.
- *
+ *
* @since 1.2
*/
public Collection<DbAttribute> getMeaningfulFKs(ObjEntity objEntity) {
@@ -301,102 +336,106 @@ public class EntityMergeSupport {
DbEntity dbEntity = objEntity.getDbEntity();
List<DbAttribute> missing = new ArrayList<DbAttribute>();
-
- Collection<DbRelationship> rels = dbEntity.getRelationships();
Collection<DbRelationship> incomingRels = getIncomingRelationships(dbEntity);
for (DbAttribute dba : dbEntity.getAttributes()) {
- if (dba.getName() == null || objEntity.getAttributeForDbAttribute(dba) != null) {
- continue;
+ if (isMissingFromObjEntity(objEntity, dba, incomingRels)) {
+ missing.add(dba);
}
+ }
- boolean removeMeaningfulPKs = removePK(dbEntity);
- if (removeMeaningfulPKs && dba.isPrimaryKey()) {
- continue;
- }
+ return missing;
+ }
- // check FK's
- boolean isFK = false;
- Iterator<DbRelationship> rit = rels.iterator();
- while (!isFK && rit.hasNext()) {
- DbRelationship rel = rit.next();
- for (DbJoin join : rel.getJoins()) {
- if (join.getSource() == dba) {
- isFK = true;
- break;
- }
- }
- }
+ protected boolean isMissingFromObjEntity(ObjEntity entity, DbAttribute dbAttribute, Collection<DbRelationship> incomingRels) {
- if (!removeMeaningfulPKs) {
- if (!dba.isPrimaryKey() && isFK) {
- continue;
- }
- } else {
- if (isFK) {
- continue;
+ if (dbAttribute.getName() == null || entity.getAttributeForDbAttribute(dbAttribute) != null) {
+ return false;
+ }
+
+ boolean removeMeaningfulPKs = removePK(dbAttribute.getEntity());
+ if (removeMeaningfulPKs && dbAttribute.isPrimaryKey()) {
+ return false;
+ }
+
+ // check FK's
+ boolean isFK = false;
+ Iterator<DbRelationship> rit = dbAttribute.getEntity().getRelationships().iterator();
+ while (!isFK && rit.hasNext()) {
+ DbRelationship rel = rit.next();
+ for (DbJoin join : rel.getJoins()) {
+ if (join.getSource() == dbAttribute) {
+ isFK = true;
+ break;
}
}
+ }
- // check incoming relationships
- rit = incomingRels.iterator();
- while (!isFK && rit.hasNext()) {
- DbRelationship rel = rit.next();
- for (DbJoin join : rel.getJoins()) {
- if (join.getTarget() == dba) {
- isFK = true;
- break;
- }
- }
+ if (!removeMeaningfulPKs) {
+ if (!dbAttribute.isPrimaryKey() && isFK) {
+ return false;
}
+ } else {
+ if (isFK) {
+ return false;
+ }
+ }
- if (!removeMeaningfulPKs) {
- if (!dba.isPrimaryKey() && isFK) {
- continue;
- }
- } else {
- if (isFK) {
- continue;
+ // check incoming relationships
+ rit = incomingRels.iterator();
+ while (!isFK && rit.hasNext()) {
+ DbRelationship rel = rit.next();
+ for (DbJoin join : rel.getJoins()) {
+ if (join.getTarget() == dbAttribute) {
+ isFK = true;
+ break;
}
}
+ }
- missing.add(dba);
+ if (!removeMeaningfulPKs) {
+ if (!dbAttribute.isPrimaryKey() && isFK) {
+ return false;
+ }
+ } else {
+ if (isFK) {
+ return false;
+ }
}
- return missing;
+ return true;
}
- private Collection<DbRelationship> getIncomingRelationships(DbEntity entity) {
- Collection<DbRelationship> incoming = new ArrayList<DbRelationship>();
+ protected boolean isMissingFromObjEntity(ObjEntity entity, DbRelationship dbRelationship) {
+ return dbRelationship.getName() != null && entity.getRelationshipForDbRelationship(dbRelationship) == null;
+ }
- for (DbEntity nextEntity : entity.getDataMap().getDbEntities()) {
- for (DbRelationship relationship : nextEntity.getRelationships()) {
+ private Collection<DbRelationship> getIncomingRelationships(DbEntity entity) {
+ Collection<DbRelationship> incoming = new ArrayList<DbRelationship>();
- // TODO: PERFORMANCE 'getTargetEntity' is generally slow, called
- // in this iterator it is showing (e.g. in YourKit profiles)..
- // perhaps use cheaper 'getTargetEntityName()' or even better -
- // pre-cache all relationships by target entity to avoid O(n)
- // search ?
- // (need to profile to prove the difference)
- if (entity == relationship.getTargetEntity()) {
- incoming.add(relationship);
- }
- }
- }
+ for (DbEntity nextEntity : entity.getDataMap().getDbEntities()) {
+ for (DbRelationship relationship : nextEntity.getRelationships()) {
- return incoming;
- }
+ // TODO: PERFORMANCE 'getTargetEntity' is generally slow, called
+ // in this iterator it is showing (e.g. in YourKit profiles)..
+ // perhaps use cheaper 'getTargetEntityName()' or even better -
+ // pre-cache all relationships by target entity to avoid O(n)
+ // search ?
+ // (need to profile to prove the difference)
+ if (entity == relationship.getTargetEntity()) {
+ incoming.add(relationship);
+ }
+ }
+ }
+
+ return incoming;
+ }
protected List<DbRelationship> getRelationshipsToAdd(ObjEntity objEntity) {
List<DbRelationship> missing = new ArrayList<DbRelationship>();
for (DbRelationship dbRel : objEntity.getDbEntity().getRelationships()) {
- // check if adding it makes sense at all
- if (dbRel.getName() == null) {
- continue;
- }
-
- if (objEntity.getRelationshipForDbRelationship(dbRel) == null) {
+ if (isMissingFromObjEntity(objEntity, dbRel)) {
missing.add(dbRel);
}
}
@@ -472,8 +511,8 @@ public class EntityMergeSupport {
}
/**
- * @since 4.0
* @param usePrimitives
+ * @since 4.0
*/
public void setUsePrimitives(boolean usePrimitives) {
this.usePrimitives = usePrimitives;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/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 d6af992..aa04b5f 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -31,6 +31,7 @@ CAY-2106 cayenne-crypto: allow DI contribution of type converters inside ValueTr
CAY-2107 cayenne-crypto: Lazy initialization of crypto subsystem
CAY-2111 Unbind transaction object from the current thread for iterated queries
CAY-2112 Expose callback for "performInTransaction"
+CAY-2113 cdbimport: Reverse-engineering reinstates previously ignored columns
Bug Fixes: