You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2019/05/21 14:42:20 UTC
[cayenne] 02/02: CAY-2582 Double insert of manyToMany relationship
mapped to Set test case from PR #385
This is an automated email from the ASF dual-hosted git repository.
ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 326f1de071cc871561891557baf5879bd1ba06ce
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Tue May 21 17:24:07 2019 +0300
CAY-2582 Double insert of manyToMany relationship mapped to Set
test case from PR #385
---
.../java/org/apache/cayenne/ManyToManyJoinIT.java | 51 ++++++++++
.../relationships_many_to_many_join/Author.java | 9 ++
.../relationships_many_to_many_join/Song.java | 9 ++
.../auto/_Author.java | 86 ++++++++++++++++
.../auto/_Song.java | 110 +++++++++++++++++++++
.../cayenne/unit/di/server/CayenneProjects.java | 1 +
.../cayenne/unit/di/server/SchemaBuilder.java | 2 +-
.../cayenne-relationships-many-to-many-join.xml | 7 ++
.../relationships-many-to-many-join.map.xml | 38 +++++++
9 files changed, 312 insertions(+), 1 deletion(-)
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/ManyToManyJoinIT.java b/cayenne-server/src/test/java/org/apache/cayenne/ManyToManyJoinIT.java
new file mode 100644
index 0000000..0949b5e
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/ManyToManyJoinIT.java
@@ -0,0 +1,51 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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;
+
+import static org.junit.Assert.*;
+
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.testdo.relationships_many_to_many_join.Author;
+import org.apache.cayenne.testdo.relationships_many_to_many_join.Song;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.junit.Test;
+
+@UseServerRuntime(CayenneProjects.RELATIONSHIPS_MANY_TO_MANY_JOIN_PROJECT)
+public class ManyToManyJoinIT extends ServerCase {
+
+ @Inject
+ private ObjectContext context;
+
+ @Test
+ public void testManyToManyJoinWithFlattenedRelationship() throws Exception {
+ Author author = context.newObject(Author.class);
+ author.setName("Bob Dylan");
+
+ Song song = context.newObject(Song.class);
+ song.setName("House of the Rising Sun");
+
+ song.addToAuthors(author);
+
+ context.commitChanges();
+ assertEquals(author, song.getAuthors().iterator().next());
+ }
+
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/Author.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/Author.java
new file mode 100644
index 0000000..a50741e
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/Author.java
@@ -0,0 +1,9 @@
+package org.apache.cayenne.testdo.relationships_many_to_many_join;
+
+import org.apache.cayenne.testdo.relationships_many_to_many_join.auto._Author;
+
+public class Author extends _Author {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/Song.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/Song.java
new file mode 100644
index 0000000..8df7056
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/Song.java
@@ -0,0 +1,9 @@
+package org.apache.cayenne.testdo.relationships_many_to_many_join;
+
+import org.apache.cayenne.testdo.relationships_many_to_many_join.auto._Song;
+
+public class Song extends _Song {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/auto/_Author.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/auto/_Author.java
new file mode 100644
index 0000000..11554d9
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/auto/_Author.java
@@ -0,0 +1,86 @@
+package org.apache.cayenne.testdo.relationships_many_to_many_join.auto;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.Property;
+
+/**
+ * Class _Author was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _Author extends BaseDataObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final String AUTHOR_ID_PK_COLUMN = "AUTHOR_ID";
+
+ public static final Property<String> NAME = Property.create("name", String.class);
+
+ protected String name;
+
+
+ public void setName(String name) {
+ beforePropertyWrite("name", this.name, name);
+ this.name = name;
+ }
+
+ public String getName() {
+ beforePropertyRead("name");
+ return this.name;
+ }
+
+ @Override
+ public Object readPropertyDirectly(String propName) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch(propName) {
+ case "name":
+ return this.name;
+ default:
+ return super.readPropertyDirectly(propName);
+ }
+ }
+
+ @Override
+ public void writePropertyDirectly(String propName, Object val) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (propName) {
+ case "name":
+ this.name = (String)val;
+ break;
+ default:
+ super.writePropertyDirectly(propName, val);
+ }
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ writeSerialized(out);
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ readSerialized(in);
+ }
+
+ @Override
+ protected void writeState(ObjectOutputStream out) throws IOException {
+ super.writeState(out);
+ out.writeObject(this.name);
+ }
+
+ @Override
+ protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ super.readState(in);
+ this.name = (String)in.readObject();
+ }
+
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/auto/_Song.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/auto/_Song.java
new file mode 100644
index 0000000..15160ca
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/relationships_many_to_many_join/auto/_Song.java
@@ -0,0 +1,110 @@
+package org.apache.cayenne.testdo.relationships_many_to_many_join.auto;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Set;
+
+import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.Property;
+import org.apache.cayenne.testdo.relationships_many_to_many_join.Author;
+
+/**
+ * Class _Song was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _Song extends BaseDataObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final String SONG_ID_PK_COLUMN = "SONG_ID";
+
+ public static final Property<String> NAME = Property.create("name", String.class);
+ public static final Property<Set<Author>> AUTHORS = Property.create("authors", Set.class);
+
+ protected String name;
+
+ protected Object authors;
+
+ public void setName(String name) {
+ beforePropertyWrite("name", this.name, name);
+ this.name = name;
+ }
+
+ public String getName() {
+ beforePropertyRead("name");
+ return this.name;
+ }
+
+ public void addToAuthors(Author obj) {
+ addToManyTarget("authors", obj, true);
+ }
+
+ public void removeFromAuthors(Author obj) {
+ removeToManyTarget("authors", obj, true);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Set<Author> getAuthors() {
+ return (Set<Author>)readProperty("authors");
+ }
+
+ @Override
+ public Object readPropertyDirectly(String propName) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch(propName) {
+ case "name":
+ return this.name;
+ case "authors":
+ return this.authors;
+ default:
+ return super.readPropertyDirectly(propName);
+ }
+ }
+
+ @Override
+ public void writePropertyDirectly(String propName, Object val) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (propName) {
+ case "name":
+ this.name = (String)val;
+ break;
+ case "authors":
+ this.authors = val;
+ break;
+ default:
+ super.writePropertyDirectly(propName, val);
+ }
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ writeSerialized(out);
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ readSerialized(in);
+ }
+
+ @Override
+ protected void writeState(ObjectOutputStream out) throws IOException {
+ super.writeState(out);
+ out.writeObject(this.name);
+ out.writeObject(this.authors);
+ }
+
+ @Override
+ protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ super.readState(in);
+ this.name = (String)in.readObject();
+ this.authors = in.readObject();
+ }
+
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
index 2d6d3f9..ed67478 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
@@ -61,6 +61,7 @@ public class CayenneProjects {
public static final String REFLEXIVE_PROJECT = "cayenne-reflexive.xml";
public static final String RELATIONSHIPS_PROJECT = "cayenne-relationships.xml";
public static final String RELATIONSHIPS_ACTIVITY_PROJECT = "cayenne-relationships-activity.xml";
+ public static final String RELATIONSHIPS_MANY_TO_MANY_JOIN_PROJECT = "cayenne-relationships-many-to-many-join.xml";
public static final String RELATIONSHIPS_CHILD_MASTER_PROJECT = "cayenne-relationships-child-master.xml";
public static final String RELATIONSHIPS_CLOB_PROJECT = "cayenne-relationships-clob.xml";
public static final String RELATIONSHIPS_COLLECTION_TO_MANY_PROJECT = "cayenne-relationships-collection-to-many.xml";
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
index 42e5658..75a79ee 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
@@ -74,7 +74,7 @@ public class SchemaBuilder {
"locking.map.xml", "soft-delete.map.xml", "empty.map.xml", "relationships.map.xml",
"relationships-activity.map.xml", "relationships-delete-rules.map.xml",
"relationships-collection-to-many.map.xml", "relationships-child-master.map.xml",
- "relationships-clob.map.xml", "relationships-flattened.map.xml", "relationships-set-to-many.map.xml",
+ "relationships-clob.map.xml", "relationships-flattened.map.xml", "relationships-many-to-many-join.map.xml", "relationships-set-to-many.map.xml",
"relationships-to-many-fk.map.xml", "relationships-to-one-fk.map.xml", "return-types.map.xml",
"uuid.map.xml", "multi-tier.map.xml", "reflexive.map.xml", "delete-rules.map.xml",
"lifecycle-callbacks-order.map.xml", "lifecycles.map.xml", "map-to-many.map.xml", "toone.map.xml", "meaningful-pk.map.xml",
diff --git a/cayenne-server/src/test/resources/cayenne-relationships-many-to-many-join.xml b/cayenne-server/src/test/resources/cayenne-relationships-many-to-many-join.xml
new file mode 100644
index 0000000..0121356
--- /dev/null
+++ b/cayenne-server/src/test/resources/cayenne-relationships-many-to-many-join.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://cayenne.apache.org/schema/10/domain https://cayenne.apache.org/schema/10/domain.xsd"
+ project-version="10">
+ <map name="relationships-many-to-many-join"/>
+</domain>
diff --git a/cayenne-server/src/test/resources/relationships-many-to-many-join.map.xml b/cayenne-server/src/test/resources/relationships-many-to-many-join.map.xml
new file mode 100644
index 0000000..38ef803
--- /dev/null
+++ b/cayenne-server/src/test/resources/relationships-many-to-many-join.map.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap https://cayenne.apache.org/schema/10/modelMap.xsd"
+ project-version="10">
+ <property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_many_to_many_join"/>
+ <db-entity name="X_AUTHOR">
+ <db-attribute name="AUTHOR_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ <db-attribute name="AUTHOR_NAME" type="VARCHAR" isMandatory="true" length="50"/>
+ </db-entity>
+ <db-entity name="X_SONG">
+ <db-attribute name="SONG_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ <db-attribute name="SONG_NAME" type="VARCHAR" isMandatory="true" length="50"/>
+ </db-entity>
+ <db-entity name="X_SONGAUTHOR">
+ <db-attribute name="AUTHOR_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ <db-attribute name="SONG_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ </db-entity>
+ <obj-entity name="Author" className="org.apache.cayenne.testdo.relationships_many_to_many_join.Author" dbEntityName="X_AUTHOR">
+ <obj-attribute name="name" type="java.lang.String" db-attribute-path="AUTHOR_NAME"/>
+ </obj-entity>
+ <obj-entity name="Song" className="org.apache.cayenne.testdo.relationships_many_to_many_join.Song" dbEntityName="X_SONG">
+ <obj-attribute name="name" type="java.lang.String" db-attribute-path="SONG_NAME"/>
+ </obj-entity>
+ <db-relationship name="songAuthor" source="X_AUTHOR" target="X_SONGAUTHOR" toDependentPK="true" toMany="true">
+ <db-attribute-pair source="AUTHOR_ID" target="AUTHOR_ID"/>
+ </db-relationship>
+ <db-relationship name="songAuthor" source="X_SONG" target="X_SONGAUTHOR" toDependentPK="true" toMany="true">
+ <db-attribute-pair source="SONG_ID" target="SONG_ID"/>
+ </db-relationship>
+ <db-relationship name="song" source="X_SONGAUTHOR" target="X_SONG">
+ <db-attribute-pair source="SONG_ID" target="SONG_ID"/>
+ </db-relationship>
+ <db-relationship name="author" source="X_SONGAUTHOR" target="X_AUTHOR">
+ <db-attribute-pair source="AUTHOR_ID" target="AUTHOR_ID"/>
+ </db-relationship>
+ <obj-relationship name="authors" source="Song" target="Author" collection-type="java.util.Set" deleteRule="Cascade" db-relationship-path="songAuthor.author"/>
+</data-map>