Repository: cayenne Updated Branches: refs/heads/master 44642ea58 -> c8ff4355f
fix relationships loading Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/aaafe117 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/aaafe117 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/aaafe117 Branch: refs/heads/master Commit: aaafe117143e256a7b48692485b22c9d10538477 Parents: 44642ea Author: alexkolonitsky <alex.kolonit...@gmail.com> Authored: Thu Jan 8 20:49:26 2015 +0300 Committer: alexkolonitsky <alex.kolonit...@gmail.com> Committed: Thu Jan 8 20:49:26 2015 +0300 ---------------------------------------------------------------------- .../org/apache/cayenne/access/DbLoader.java | 69 ++++----- .../access/loader/LoggingDbLoaderDelegate.java | 20 +-- .../org/apache/cayenne/map/DbRelationship.java | 40 ++++-- .../org/apache/cayenne/map/Relationship.java | 6 +- .../apache/cayenne/map/naming/ExportedKey.java | 18 ++- .../merge/DropRelationshipToModelIT.java | 7 +- .../apache/cayenne/merge/MergerFactoryIT.java | 13 +- cayenne-tools/pom.xml | 5 + .../cayenne/tools/CayenneGeneratorTask.java | 11 +- .../cayenne/tools/dbimport/DbImportAction.java | 30 ++-- .../dbimport/DbImportDbLoaderDelegate.java | 1 - .../src/main/resources/reverseEngineering.xsd | 139 +++++++++++++++++++ .../cayenne/tools/DbImporterMojoTest.java | 4 + .../cayenne/tools/dbimport/testOneToOne-pom.xml | 39 ++++++ .../tools/dbimport/testOneToOne.map.xml-result | 58 ++++++++ .../cayenne/tools/dbimport/testOneToOne.sql | 24 ++++ 16 files changed, 400 insertions(+), 84 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java index 864e4f0..f86692f 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java @@ -49,14 +49,12 @@ import org.apache.commons.logging.LogFactory; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; -import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -325,9 +323,8 @@ public class DbLoader { loadDbAttributes(config.getFiltersConfig(), tablesMap.getKey(), tablesMap.getValue()); - if (!config.isSkipPrimaryKeyLoading()) { - getPrimaryKeyForTable(tablesMap.getValue()); - } + // get primary keys for each table and store it in dbEntity + getPrimaryKeyForTable(tablesMap.getValue()); } return dbEntityList; @@ -366,8 +363,6 @@ public class DbLoader { ResultSet rs = getMetaData().getColumns(path.catalog, path.schema, WILDCARD, WILDCARD); try { - Set<String> columns = new HashSet<String>(); - while (rs.next()) { // for a reason not quiet apparent to me, Oracle sometimes // returns duplicate record sets for the same table, messing up table @@ -382,7 +377,7 @@ public class DbLoader { continue; } - DbAttribute attr = loadDbAttribute(columns, rs); + DbAttribute attr = loadDbAttribute(rs); attr.setEntity(dbEntity); Filter<DbAttribute> filter = filters.filter(new DbPath(dbEntity.getCatalog(), dbEntity.getSchema(), dbEntity.getName())).columnFilter(); if (!filter.isInclude(attr)) { @@ -404,14 +399,7 @@ public class DbLoader { } } - private DbAttribute loadDbAttribute(Set<String> columns, ResultSet rs) throws SQLException { - if (columns.isEmpty()) { - ResultSetMetaData rsMetaData = rs.getMetaData(); - for (int i = 1; i <= rsMetaData.getColumnCount(); i++) { - columns.add(rsMetaData.getColumnLabel(i)); - } - } - + private DbAttribute loadDbAttribute(ResultSet rs) throws SQLException { // gets attribute's (column's) information int columnType = rs.getInt("DATA_TYPE"); @@ -433,7 +421,11 @@ public class DbLoader { decimalDigits, rs.getBoolean("NULLABLE")); - if (columns.contains("IS_AUTOINCREMENT")) { + if (adapter.supportsGeneratedKeys()) { + + // TODO: this actually throws on some drivers... need to + // ensure that 'supportsGeneratedKeys' check is enough + // to prevent an exception here. String autoIncrement = rs.getString("IS_AUTOINCREMENT"); if ("YES".equals(autoIncrement)) { attr.setGenerated(true); @@ -443,7 +435,8 @@ public class DbLoader { } /** - * Creates an ObjEntity for each DbEntity in the map. + * Creates an ObjEntity for each DbEntity in the map. ObjEntities are + * created empty without */ protected Collection<ObjEntity> loadObjEntities(DataMap map, DbLoaderConfiguration config, Collection<DbEntity> entities) { if (entities.isEmpty()) { @@ -518,28 +511,29 @@ public class DbLoader { continue; } + // forwardRelationship is a reference from table with primary key DbRelationship forwardRelationship = new DbRelationship(generateName(pkEntity, key, true)); forwardRelationship.setSourceEntity(pkEntity); forwardRelationship.setTargetEntity(fkEntity); + // forwardRelationship is a reference from table with foreign key, it is what exactly we load from db DbRelationshipDetected reverseRelationship = new DbRelationshipDetected(generateName(fkEntity, key, false)); reverseRelationship.setFkName(key.getFKName()); reverseRelationship.setSourceEntity(fkEntity); reverseRelationship.setTargetEntity(pkEntity); reverseRelationship.setToMany(false); - if (delegate.dbRelationshipLoaded(fkEntity, reverseRelationship)) { - fkEntity.addRelationship(reverseRelationship); - } - boolean toPK = createAndAppendJoins(exportedKeys, pkEntity, fkEntity, forwardRelationship, reverseRelationship); + createAndAppendJoins(exportedKeys, pkEntity, fkEntity, forwardRelationship, reverseRelationship); - forwardRelationship.setToDependentPK(toPK); - - boolean isOneToOne = toPK && fkEntity.getPrimaryKeys().size() - == forwardRelationship.getJoins().size(); + boolean isOneToOne = isOneToOne(fkEntity, forwardRelationship); + forwardRelationship.setToDependentPK(isOneToOne); forwardRelationship.setToMany(!isOneToOne); forwardRelationship.setName(generateName(pkEntity, key, !isOneToOne)); + + if (delegate.dbRelationshipLoaded(fkEntity, reverseRelationship)) { + fkEntity.addRelationship(reverseRelationship); + } if (delegate.dbRelationshipLoaded(pkEntity, forwardRelationship)) { pkEntity.addRelationship(forwardRelationship); } @@ -547,8 +541,21 @@ public class DbLoader { } } - private boolean createAndAppendJoins(Set<ExportedKey> exportedKeys, DbEntity pkEntity, DbEntity fkEntity, DbRelationship forwardRelationship, DbRelationshipDetected reverseRelationship) { - boolean toPK = true; + private boolean isOneToOne(DbEntity fkEntity, DbRelationship forwardRelationship) { + if (fkEntity.getPrimaryKeys().size() != forwardRelationship.getJoins().size()) { + return false; + } + + for (DbJoin dbJoin : forwardRelationship.getJoins()) { + if (!dbJoin.getTarget().isPrimaryKey()) { + return false; + } + } + + return true; + } + + private void createAndAppendJoins(Set<ExportedKey> exportedKeys, DbEntity pkEntity, DbEntity fkEntity, DbRelationship forwardRelationship, DbRelationshipDetected reverseRelationship) { for (ExportedKey exportedKey : exportedKeys) { // Create and append joins String pkName = exportedKey.getPKColumnName(); @@ -569,12 +576,7 @@ public class DbLoader { forwardRelationship.addJoin(new DbJoin(forwardRelationship, pkName, fkName)); reverseRelationship.addJoin(new DbJoin(reverseRelationship, fkName, pkName)); - - if (!pkAtt.isPrimaryKey()) { - toPK = false; - } } - return toPK; } private Map<String, Set<ExportedKey>> loadExportedKeys(DbLoaderConfiguration config, DbPath dbPath, Map<String, DbEntity> tables) throws SQLException { @@ -760,6 +762,7 @@ public class DbLoader { * @since 4.0 */ public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException { + LOGGER.info("Schema loading..."); Map<DbPath, Map<String, DbEntity>> tables = getTables(config, config.getTableTypes()); List<DbEntity> entities = loadDbEntities(dataMap, config, tables); http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java index d5e69f4..8c77a87 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java @@ -36,37 +36,41 @@ public class LoggingDbLoaderDelegate extends DefaultDbLoaderDelegate { @Override public void dbEntityAdded(DbEntity entity) { - logger.info("Add dbEntity: " + entity.getFullyQualifiedName()); + logger.info(" Table: " + entity.getFullyQualifiedName()); } @Override public void dbEntityRemoved(DbEntity entity) { - logger.info("Del dbEntity: " + entity.getFullyQualifiedName()); + logger.info(" Table removed: " + entity.getFullyQualifiedName()); } @Override public boolean dbRelationship(DbEntity entity) { - logger.info(" Relationships for " + entity.getFullyQualifiedName()); + if (logger.isDebugEnabled()) { + logger.debug(" Relationships for " + entity.getFullyQualifiedName()); + } return true; } @Override public boolean dbRelationshipLoaded(DbEntity entity, DbRelationship relationship) { - if (logger.isDebugEnabled()) { - logger.debug(" Relationship : " + entity.getName() + "; " + relationship.toString()); - } + logger.info(" " + relationship); return true; } @Override public void objEntityAdded(ObjEntity entity) { - logger.info("Add objEntity: " + entity.getName()); + if (logger.isDebugEnabled()) { + logger.debug(" Class: " + entity.getName()); + } } @Override public void objEntityRemoved(ObjEntity entity) { - logger.info("Del objEntity: " + entity.getName()); + if (logger.isDebugEnabled()) { + logger.debug(" Class removed: " + entity.getName()); + } } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java index 5234ff4..12bfbf9 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java @@ -33,6 +33,7 @@ import org.apache.cayenne.util.Util; import org.apache.cayenne.util.XMLEncoder; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Transformer; +import org.apache.commons.lang.StringUtils; /** * A DbRelationship is a descriptor of a database inter-table relationship based @@ -40,17 +41,18 @@ import org.apache.commons.collections.Transformer; */ public class DbRelationship extends Relationship implements ConfigurationNode { - // The columns through which the join is implemented. + /** + * The columns through which the join is implemented. + */ protected List<DbJoin> joins = new ArrayList<DbJoin>(2); - // Is relationship from source to target points to dependent primary - // key (primary key column of destination table that is also a FK to the - // source - // column) + /** + * Is relationship from source to target points to dependent primary key (primary key column of destination table + * that is also a FK to the source column) + */ protected boolean toDependentPK; public DbRelationship() { - super(); } public DbRelationship(String name) { @@ -122,7 +124,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode { */ public Collection<DbAttribute> getTargetAttributes() { if (joins.size() == 0) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } return CollectionUtils.collect(joins, JoinTransformers.targetExtractor); @@ -135,7 +137,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode { */ public Collection<DbAttribute> getSourceAttributes() { if (joins.size() == 0) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } return CollectionUtils.collect(joins, JoinTransformers.sourceExtractor); @@ -148,7 +150,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode { * @since 1.0.5 */ public DbRelationship createReverseRelationship() { - DbEntity targetEntity = (DbEntity) getTargetEntity(); + DbEntity targetEntity = getTargetEntity(); DbRelationship reverse = new DbRelationship(); reverse.setSourceEntity(targetEntity); @@ -535,4 +537,24 @@ public class DbRelationship extends Relationship implements ConfigurationNode { && Util.nullSafeEquals(j.targetName, this.targetName); } } + + @Override + public String toString() { + String res = "Db Relationship : " + (toMany ? "toMany" : "toOne "); + + String sourceEntityName = getSourceEntityName(); + String targetEntityName = getTargetEntityName(); + for (DbJoin join : joins) { + res += " (" + sourceEntityName + "." + join.getSourceName() + ", " + targetEntityName + "." + join.getTargetName() + ")"; + } + + return res; + } + + public String getSourceEntityName() { + if (this.sourceEntity == null) { + return null; + } + return this.sourceEntity.name; + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java index 1c34172..ecc0f80 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java @@ -159,9 +159,9 @@ public abstract class Relationship implements CayenneMapEntry, XMLSerializable, */ @Override public String toString() { - return new ToStringBuilder(this).append("name", getName()).append( - "toMany", - isToMany()).toString(); + return new ToStringBuilder(this) + .append("name", getName()) + .append("toMany", isToMany()).toString(); } /** http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java index 42697fe..ab8229f 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java @@ -28,6 +28,19 @@ import java.sql.SQLException; /** * ExportedKey is an representation of relationship between two tables * in database. It can be used for creating names for relationships + * + * Example: + * Table A with primary key ID + * Table B with primary key ID and foreign key A_ID + * + * In that case ExportedKey will be: + * pkTable: A + * pkColumn: A.ID + * fkTable: B + * fkColumn: B.A_ID + * fkName: name of foreign key + * pkName: + * keySeq: TODO * */ public class ExportedKey implements Comparable { @@ -200,11 +213,10 @@ public class ExportedKey implements Comparable { @Override public String toString() { - return getStrKey() + " # " + keySeq - + "(" + pkColumn + " <- " + fkColumn + ")"; + return getStrKey() + " # " + keySeq; } public String getStrKey() { - return pkTable + "." + pkName + " <- " + fkTable + "." + fkName; + return pkTable + "." + pkColumn + " <- " + fkTable + "." + fkColumn; } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java index e235109..3505971 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java @@ -130,7 +130,12 @@ public class DropRelationshipToModelIT extends MergeCase { dbEntity1.removeRelationship(rel1To2.getName()); dbEntity2.removeAttribute(e2col2.getName()); List<MergerToken> tokens = createMergeTokens(); - assertTokens(tokens, 3, 0); + /** + * Add Relationship NEW_TABLE->NEW_TABLE2 To Model + * Drop Relationship NEW_TABLE2->NEW_TABLE To DB + * Drop Column NEW_TABLE2.FK To DB + * */ + assertTokens(tokens, 2, 1); for (MergerToken token : tokens) { if (token.getDirection().isToDb()) { execute(token); http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java index 409f1c9..e1db050 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java @@ -219,8 +219,11 @@ public class MergerFactoryIT extends MergeCase { dbEntity.removeRelationship(r1.getName()); artistDbEntity.removeRelationship(r2.getName()); resolver.refreshMappingCache(); - assertTokensAndExecute(2, 0); -// assertTokensAndExecute(1, 1); + /* + * Db -Rel 'toArtistR1' - NEW_TABLE 1 -> 1 ARTIST" +r2 = * Db -Rel 'toNewTableR2' - ARTIST 1 -> * NEW_TABLE" + * */ + assertTokensAndExecute(1, 1); assertTokensAndExecute(0, 0); // clear up @@ -277,7 +280,11 @@ public class MergerFactoryIT extends MergeCase { dbEntity.removeRelationship(r1.getName()); artistDbEntity.removeRelationship(r2.getName()); resolver.refreshMappingCache(); - assertTokensAndExecute(2, 0); + /* + * Add Relationship ARTIST->NEW_TABLE To Model + * Drop Relationship NEW_TABLE->ARTIST To DB + * */ + assertTokensAndExecute(1, 1); assertTokensAndExecute(0, 0); // clear up http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/pom.xml ---------------------------------------------------------------------- diff --git a/cayenne-tools/pom.xml b/cayenne-tools/pom.xml index a97dd13..630c92d 100644 --- a/cayenne-tools/pom.xml +++ b/cayenne-tools/pom.xml @@ -165,6 +165,11 @@ <plugin> <artifactId>maven-pmd-plugin</artifactId> </plugin> + <plugin> + <groupId>xsddoc</groupId> + <artifactId>maven-xsddoc-plugin</artifactId> + <version>1.0</version> + </plugin> </plugins> </build> </project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java ---------------------------------------------------------------------- diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java index dcd36e6..26ae00d 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java @@ -73,16 +73,9 @@ public class CayenneGeneratorTask extends CayenneTask { } protected ClassGenerationAction createGeneratorAction() { - ClassGenerationAction action; - if (client) { - action = new ClientClassGenerationAction(); - action.setContext(getVppContext()); - } - else { - action = new ClassGenerationAction(); - action.setContext(getVppContext()); - } + ClassGenerationAction action = client ? new ClientClassGenerationAction() : new ClassGenerationAction(); + action.setContext(getVppContext()); action.setDestDir(destDir); action.setEncoding(encoding); action.setMakePairs(makepairs); http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java ---------------------------------------------------------------------- diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java index bf981ee..3ff9278 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java @@ -110,7 +110,8 @@ public class DbImportAction { List<MergerToken> mergeTokens = new DbMerger(mergerFactory) .createMergeTokens(existing, loadedFomDb, config.getDbLoaderConfig()); if (mergeTokens.isEmpty()) { - logger.info("No changes to import."); + logger.info(""); + logger.info("Detected changes: No changes to import."); return; } @@ -122,6 +123,7 @@ public class DbImportAction { } private Collection<MergerToken> log(List<MergerToken> tokens) { + logger.info(""); logger.info("Detected changes: "); for (MergerToken token : tokens) { logger.info(String.format(" %-20s %s", token.getTokenName(), token.getTokenValue())); @@ -154,7 +156,7 @@ public class DbImportAction { /** * Performs configured schema operations via DbGenerator. */ - public DataMap execute(ModelMergeDelegate mergeDelegate, DataMap dataMap, Collection<MergerToken> tokens) { + private DataMap execute(ModelMergeDelegate mergeDelegate, DataMap dataMap, Collection<MergerToken> tokens) { MergerContext mergerContext = new ExecutingMergerContext( dataMap, null, null, mergeDelegate); @@ -190,18 +192,18 @@ public class DbImportAction { projectSaver.save(project); } - private DataMap load(DbImportConfiguration config, DbAdapter adapter, Connection connection) throws Exception { - DataMap dataMap = config.createDataMap(); + private DataMap load(DbImportConfiguration config, DbAdapter adapter, Connection connection) throws Exception { + DataMap dataMap = config.createDataMap(); - try { - DbLoader loader = config.createLoader(adapter, connection, config.createLoaderDelegate()); - loader.load(dataMap, config.getDbLoaderConfig()); - } finally { - if (connection != null) { - connection.close(); - } - } + try { + DbLoader loader = config.createLoader(adapter, connection, config.createLoaderDelegate()); + loader.load(dataMap, config.getDbLoaderConfig()); + } finally { + if (connection != null) { + connection.close(); + } + } - return dataMap; - } + return dataMap; + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java ---------------------------------------------------------------------- diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java index a97fd03..e3fbc01 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java @@ -19,7 +19,6 @@ package org.apache.cayenne.tools.dbimport; -import org.apache.cayenne.access.DbLoaderDelegate; import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.ObjEntity; http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/src/main/resources/reverseEngineering.xsd ---------------------------------------------------------------------- diff --git a/cayenne-tools/src/main/resources/reverseEngineering.xsd b/cayenne-tools/src/main/resources/reverseEngineering.xsd new file mode 100644 index 0000000..6905386 --- /dev/null +++ b/cayenne-tools/src/main/resources/reverseEngineering.xsd @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. + --> +<xs:schema attributeFormDefault="unqualified" + elementFormDefault="qualified" + xmlns:xs="http://www.w3.org/2001/XMLSchema"> + + <xs:complexType name="PatternParamType" mixed="true"> + <xs:annotation> + <xs:documentation> + At least one of 3 options ot fill pattern information should be used + 1) <tag>pattarn<tag> + 2) <tag pattern="pattern" /> + 3) <tag> + <pattern>pattern</pattern> + </tag> + </xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element type="xs:string" name="pattern" minOccurs="0"/> + </xs:sequence> + <xs:attribute type="xs:string" name="pattern" use="optional"/> + </xs:complexType> + + <xs:complexType name="IncludeTableType" mixed="true"> + <xs:complexContent> + <xs:extension base="PatternParamType"> + <xs:sequence> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="includeColumn" type="PatternParamType" /> + <xs:element name="excludeColumn" type="PatternParamType" /> + </xs:choice> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> + + <xs:complexType name="FilterContainerType"> + <xs:sequence> + <xs:choice minOccurs="1" maxOccurs="unbounded"> + <xs:element name="includeTable" type="IncludeTableType" /> + <xs:element name="excludeTable" type="PatternParamType" /> + <xs:element name="includeColumn" type="PatternParamType" /> + <xs:element name="excludeColumn" type="PatternParamType" /> + <xs:element name="includeProcedure" type="PatternParamType" /> + <xs:element name="excludeProcedure" type="PatternParamType" /> + </xs:choice> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="SchemaType" mixed="true"> + <xs:annotation> + <xs:documentation> + At least one of 3 options to provide schema name can be used: + 1) <schema>name<schema> + 2) <schema name="name" /> + 3) <schema> + <name>name</name> + </schema> + </xs:documentation> + </xs:annotation> + <xs:complexContent> + <xs:extension base="FilterContainerType"> + <xs:sequence> + <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1" /> + </xs:sequence> + <xs:attribute type="xs:string" name="name" use="optional" /> + </xs:extension> + </xs:complexContent> + </xs:complexType> + + <xs:complexType name="CatalogType" mixed="true"> + <xs:annotation> + <xs:documentation> + At least one of 3 options to provide schema name can be used: + 1) <catalog>name<catalog> + 2) <catalog name="name" /> + 3) <catalog> + <name>name</name> + </catalog> + </xs:documentation> + </xs:annotation> + <xs:complexContent> + <xs:extension base="FilterContainerType"> + <xs:sequence> + <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1" /> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="schema" type="SchemaType" /> + </xs:choice> + </xs:sequence> + <xs:attribute type="xs:string" name="name" use="optional" /> + </xs:extension> + </xs:complexContent> + </xs:complexType> + + <xs:complexType name="ReverseEngineeringType"> + <xs:annotation> + <xs:documentation> + <!-- TODO --> + </xs:documentation> + </xs:annotation> + <xs:complexContent> + <xs:extension base="FilterContainerType"> + <xs:sequence> + <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1" /> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="catalog" type="CatalogType" /> + <xs:element name="schema" type="SchemaType" /> + </xs:choice> + </xs:sequence> + <xs:attribute type="xs:string" name="name" use="optional" /> + </xs:extension> + </xs:complexContent> + </xs:complexType> + + <xs:element name="reverseEngineering" type="ReverseEngineeringType"> + <xs:annotation> + <!-- TODO --> + <xs:documentation> </xs:documentation> + </xs:annotation> + </xs:element> + +</xs:schema> http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java ---------------------------------------------------------------------- diff --git a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java index cf17a84..e7fc592 100644 --- a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java +++ b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java @@ -153,6 +153,10 @@ public class DbImporterMojoTest extends AbstractMojoTestCase { test("testSkipPrimaryKeyLoading"); } + public void testOneToOne() throws Exception { + test("testOneToOne"); + } + /** * Q: what happens if a relationship existed over a column that was later deleted? and âskipRelLoadingâ is true * A: it should remove relationship and column http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml ---------------------------------------------------------------------- diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml new file mode 100644 index 0000000..bee8671 --- /dev/null +++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 + http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <name>DbImporterMojo Test1</name> + + <build> + <plugins> + <plugin> + <artifactId>maven-cayenne-plugin</artifactId> + <configuration> + <map>target/test-classes/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml</map> + <driver>org.apache.derby.jdbc.EmbeddedDriver</driver> + <url>jdbc:derby:memory:DbImporterMojoTest;create=true</url> + </configuration> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/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 new file mode 100644 index 0000000..557423d --- /dev/null +++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<data-map xmlns="http://cayenne.apache.org/schema/7/modelMap" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://cayenne.apache.org/schema/7/modelMap http://cayenne.apache.org/schema/7/modelMap.xsd" + project-version="7"> + <db-entity name="PICK_SCHEDULE" schema="APP"> + <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/> + <db-attribute name="OWNER_ID" type="INTEGER" length="10"/> + <db-attribute name="SELECTED_PLAYER_ID" type="INTEGER" length="10"/> + </db-entity> + <db-entity name="PLAYER" schema="APP"> + <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/> + </db-entity> + <db-entity name="PLAYER_INFO" schema="APP"> + <db-attribute name="PLAYER_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/> + </db-entity> + <obj-entity name="PickSchedule" className="PickSchedule" dbEntityName="PICK_SCHEDULE"> + <obj-attribute name="ownerId" type="java.lang.Integer" db-attribute-path="OWNER_ID"/> + </obj-entity> + <obj-entity name="Player" className="Player" dbEntityName="PLAYER"> + </obj-entity> + <obj-entity name="PlayerInfo" className="PlayerInfo" dbEntityName="PLAYER_INFO"> + </obj-entity> + <db-relationship name="toPlayer" source="PICK_SCHEDULE" target="PLAYER" toMany="false"> + <db-attribute-pair source="SELECTED_PLAYER_ID" target="ID"/> + </db-relationship> + <db-relationship name="pickScheduleArray" source="PLAYER" target="PICK_SCHEDULE" toMany="true"> + <db-attribute-pair source="ID" target="SELECTED_PLAYER_ID"/> + </db-relationship> + <db-relationship name="toPlayer" source="PLAYER" target="PLAYER_INFO" toDependentPK="true" toMany="false"> + <db-attribute-pair source="ID" target="PLAYER_ID"/> + </db-relationship> + <db-relationship name="toPlayer" source="PLAYER_INFO" target="PLAYER" toMany="false"> + <db-attribute-pair source="PLAYER_ID" target="ID"/> + </db-relationship> + <obj-relationship name="toPlayer" source="PickSchedule" target="Player" deleteRule="Nullify" db-relationship-path="toPlayer"/> + <obj-relationship name="pickScheduleArray" source="Player" target="PickSchedule" deleteRule="Deny" db-relationship-path="pickScheduleArray"/> + <obj-relationship name="toPlayer" source="Player" target="PlayerInfo" deleteRule="Nullify" db-relationship-path="toPlayer"/> + <obj-relationship name="toPlayer" source="PlayerInfo" target="Player" deleteRule="Nullify" db-relationship-path="toPlayer"/> +</data-map> http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql ---------------------------------------------------------------------- diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql new file mode 100644 index 0000000..a279c65 --- /dev/null +++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql @@ -0,0 +1,24 @@ +CREATE TABLE player ( + id INTEGER NOT NULL, + + PRIMARY KEY (id) +); + + +-- one-to-one relationship +CREATE TABLE player_info ( + player_id INTEGER NOT NULL, + + PRIMARY KEY (player_id), + CONSTRAINT fk_player_info FOREIGN KEY (player_id) REFERENCES player (id) +); + +-- one-to-many relationship +CREATE TABLE pick_schedule ( + id INTEGER NOT NULL, + owner_id INTEGER, + selected_player_id INTEGER, + PRIMARY KEY (id), + + CONSTRAINT fk_pick_schedule_player1 FOREIGN KEY (selected_player_id) REFERENCES player (id) +)