CAY-2899 CommitLog: missing lifecycle-induced changes in `excludeFromTransaction` mode
diff --git a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogModuleExtender.java b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogModuleExtender.java
index 39d0b1d..a959219 100644
--- a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogModuleExtender.java
+++ b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogModuleExtender.java
@@ -18,12 +18,14 @@
****************************************************************/
package org.apache.cayenne.commitlog;
+import org.apache.cayenne.DataChannelSyncFilter;
import org.apache.cayenne.commitlog.meta.AnnotationCommitLogEntityFactory;
import org.apache.cayenne.commitlog.meta.CommitLogEntity;
import org.apache.cayenne.commitlog.meta.CommitLogEntityFactory;
import org.apache.cayenne.configuration.runtime.CoreModule;
import org.apache.cayenne.di.Binder;
import org.apache.cayenne.di.ListBuilder;
+import org.apache.cayenne.graph.GraphChangeHandler;
/**
* A builder of a custom extensions module for {@link CommitLogModule} that customizes its services and installs
@@ -60,6 +62,7 @@
* within the transaction, so listeners can commit their code together with the main commit.
*/
public CommitLogModuleExtender excludeFromTransaction() {
+ CoreModule.extend(binder).addSyncFilter(createDiffInitFilter(), true);
return registerFilter(false);
}
@@ -100,4 +103,17 @@
}
return commitLogListeners;
}
+
+ /**
+ * @return the filter that just initializes incoming Diff
+ */
+ private static DataChannelSyncFilter createDiffInitFilter() {
+ GraphChangeHandler noopHandler = new GraphChangeHandler() {};
+ return (originatingContext, changes, syncType, filterChain)
+ -> {
+ // see ObjectStoreGraphDiff.resolveDiff()
+ changes.apply(noopHandler);
+ return filterChain.onSync(originatingContext, changes, syncType);
+ };
+ }
}
diff --git a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilter_PreUpdate_IT.java b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilter_PreUpdate_IT.java
new file mode 100644
index 0000000..5646c4c
--- /dev/null
+++ b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilter_PreUpdate_IT.java
@@ -0,0 +1,101 @@
+/*****************************************************************
+ * 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.commitlog;
+
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.annotation.PreUpdate;
+import org.apache.cayenne.commitlog.db.AuditLog;
+import org.apache.cayenne.commitlog.db.AuditableChild5;
+import org.apache.cayenne.commitlog.model.ObjectChange;
+import org.apache.cayenne.commitlog.unit.AuditableRuntimeCase;
+import org.apache.cayenne.configuration.runtime.CoreModule;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.runtime.CayenneRuntimeBuilder;
+import org.apache.cayenne.tx.BaseTransaction;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class CommitLogFilter_PreUpdate_IT extends AuditableRuntimeCase {
+
+ protected ObjectContext context;
+ protected CommitLogListener listener;
+
+ @Override
+ protected CayenneRuntimeBuilder configureCayenne() {
+ this.listener = (originatingContext, changes) -> {
+ // assert we are not inside a transaction
+ assertNotNull(BaseTransaction.getThreadTransaction());
+
+ for (ObjectChange c : changes.getUniqueChanges()) {
+ AuditLog log = runtime.newContext().newObject(AuditLog.class);
+ log.setLog("DONE: " + c.getPostCommitId());
+ log.getObjectContext().commitChanges();
+ }
+ };
+
+ return super.configureCayenne()
+ .addModule(binder ->
+ CoreModule.extend(binder)
+ .addListenerType(MyPreUpdateListener.class)
+ )
+ .addModule(binder ->
+ CommitLogModule.extend(binder)
+ .commitLogAnnotationEntitiesOnly()
+ .addListener(listener)
+ );
+ }
+
+ @Before
+ public void before() throws Exception {
+ context = runtime.newContext();
+ auditable5.insert(1, "yy");
+ auditableChild5.insert(1, 1, "zz");
+ }
+
+ @Test
+ public void testCommitLog() throws SQLException {
+
+ AuditableChild5 auditableChild = ObjectSelect.query(AuditableChild5.class)
+ .selectOne(context);
+ assertEquals("zz", auditableChild.getCharProperty1());
+
+ auditableChild.setCharProperty1("xx");
+
+ context.commitChanges();
+
+ List<Object[]> logs = auditLog.selectAll();
+ assertEquals(2, logs.size());
+ }
+
+ public static class MyPreUpdateListener {
+
+ @PreUpdate({ AuditableChild5.class })
+ public void preUpdate( AuditableChild5 child ) {
+ child.getParent().setCharProperty1("zz");
+ }
+ }
+
+
+}
diff --git a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilter_PreUpdate_OutsideTxIT.java b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilter_PreUpdate_OutsideTxIT.java
new file mode 100644
index 0000000..ac7d7be
--- /dev/null
+++ b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilter_PreUpdate_OutsideTxIT.java
@@ -0,0 +1,101 @@
+/*****************************************************************
+ * 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.commitlog;
+
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.annotation.PreUpdate;
+import org.apache.cayenne.commitlog.db.AuditLog;
+import org.apache.cayenne.commitlog.db.AuditableChild5;
+import org.apache.cayenne.commitlog.model.ObjectChange;
+import org.apache.cayenne.commitlog.unit.AuditableRuntimeCase;
+import org.apache.cayenne.configuration.runtime.CoreModule;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.runtime.CayenneRuntimeBuilder;
+import org.apache.cayenne.tx.BaseTransaction;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class CommitLogFilter_PreUpdate_OutsideTxIT extends AuditableRuntimeCase {
+
+ protected ObjectContext context;
+ protected CommitLogListener listener;
+
+ @Override
+ protected CayenneRuntimeBuilder configureCayenne() {
+ this.listener = (originatingContext, changes) -> {
+ // assert we are not inside a transaction
+ assertNull(BaseTransaction.getThreadTransaction());
+
+ for (ObjectChange c : changes.getUniqueChanges()) {
+ AuditLog log = runtime.newContext().newObject(AuditLog.class);
+ log.setLog("DONE: " + c.getPostCommitId());
+ log.getObjectContext().commitChanges();
+ }
+ };
+
+ return super.configureCayenne()
+ .addModule(binder ->
+ CoreModule.extend(binder)
+ .addListenerType(MyPreUpdateListener.class)
+ )
+ .addModule(
+ b -> CommitLogModule.extend(b)
+ .commitLogAnnotationEntitiesOnly()
+ .excludeFromTransaction()
+ .addListener(listener)
+ );
+ }
+
+ @Before
+ public void before() throws Exception {
+ context = runtime.newContext();
+ auditable5.insert(1, "yy");
+ auditableChild5.insert(1, 1, "zz");
+ }
+
+ @Test
+ public void testCommitLog() throws SQLException {
+
+ AuditableChild5 auditableChild = ObjectSelect.query(AuditableChild5.class)
+ .selectOne(context);
+ assertEquals("zz", auditableChild.getCharProperty1());
+
+ auditableChild.setCharProperty1("xx");
+
+ context.commitChanges();
+
+ List<Object[]> logs = auditLog.selectAll();
+ assertEquals(2, logs.size());
+ }
+
+ public static class MyPreUpdateListener {
+
+ @PreUpdate({ AuditableChild5.class })
+ public void preUpdate( AuditableChild5 child ) {
+ child.getParent().setCharProperty1("zz");
+ }
+ }
+
+
+}
diff --git a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/Auditable5.java b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/Auditable5.java
new file mode 100644
index 0000000..ed13e0b
--- /dev/null
+++ b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/Auditable5.java
@@ -0,0 +1,30 @@
+/*****************************************************************
+ * 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.commitlog.db;
+
+import org.apache.cayenne.commitlog.CommitLog;
+import org.apache.cayenne.commitlog.db.auto._Auditable5;
+
+@CommitLog
+public class Auditable5 extends _Auditable5 {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/AuditableChild5.java b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/AuditableChild5.java
new file mode 100644
index 0000000..5e8c445
--- /dev/null
+++ b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/AuditableChild5.java
@@ -0,0 +1,30 @@
+/*****************************************************************
+ * 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.commitlog.db;
+
+import org.apache.cayenne.commitlog.CommitLog;
+import org.apache.cayenne.commitlog.db.auto._AuditableChild5;
+
+@CommitLog
+public class AuditableChild5 extends _AuditableChild5 {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/auto/_Auditable5.java b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/auto/_Auditable5.java
new file mode 100644
index 0000000..242db2a
--- /dev/null
+++ b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/auto/_Auditable5.java
@@ -0,0 +1,116 @@
+package org.apache.cayenne.commitlog.db.auto;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.List;
+
+import org.apache.cayenne.PersistentObject;
+import org.apache.cayenne.commitlog.db.Auditable5;
+import org.apache.cayenne.commitlog.db.AuditableChild5;
+import org.apache.cayenne.exp.property.ListProperty;
+import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
+import org.apache.cayenne.exp.property.StringProperty;
+
+/**
+ * Class _Auditable5 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 _Auditable5 extends PersistentObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final SelfProperty<Auditable5> SELF = PropertyFactory.createSelf(Auditable5.class);
+
+ public static final String ID_PK_COLUMN = "ID";
+
+ public static final StringProperty<String> CHAR_PROPERTY1 = PropertyFactory.createString("charProperty1", String.class);
+ public static final ListProperty<AuditableChild5> CHILDREN = PropertyFactory.createList("children", AuditableChild5.class);
+
+ protected String charProperty1;
+
+ protected Object children;
+
+ public void setCharProperty1(String charProperty1) {
+ beforePropertyWrite("charProperty1", this.charProperty1, charProperty1);
+ this.charProperty1 = charProperty1;
+ }
+
+ public String getCharProperty1() {
+ beforePropertyRead("charProperty1");
+ return this.charProperty1;
+ }
+
+ public void addToChildren(AuditableChild5 obj) {
+ addToManyTarget("children", obj, true);
+ }
+
+ public void removeFromChildren(AuditableChild5 obj) {
+ removeToManyTarget("children", obj, true);
+ }
+
+ @SuppressWarnings("unchecked")
+ public List<AuditableChild5> getChildren() {
+ return (List<AuditableChild5>)readProperty("children");
+ }
+
+ @Override
+ public Object readPropertyDirectly(String propName) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch(propName) {
+ case "charProperty1":
+ return this.charProperty1;
+ case "children":
+ return this.children;
+ default:
+ return super.readPropertyDirectly(propName);
+ }
+ }
+
+ @Override
+ public void writePropertyDirectly(String propName, Object val) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (propName) {
+ case "charProperty1":
+ this.charProperty1 = (String)val;
+ break;
+ case "children":
+ this.children = 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.charProperty1);
+ out.writeObject(this.children);
+ }
+
+ @Override
+ protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ super.readState(in);
+ this.charProperty1 = (String)in.readObject();
+ this.children = in.readObject();
+ }
+
+}
diff --git a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/auto/_AuditableChild5.java b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/auto/_AuditableChild5.java
new file mode 100644
index 0000000..26e66b2
--- /dev/null
+++ b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/auto/_AuditableChild5.java
@@ -0,0 +1,110 @@
+package org.apache.cayenne.commitlog.db.auto;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.cayenne.PersistentObject;
+import org.apache.cayenne.commitlog.db.Auditable5;
+import org.apache.cayenne.commitlog.db.AuditableChild5;
+import org.apache.cayenne.exp.property.EntityProperty;
+import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
+import org.apache.cayenne.exp.property.StringProperty;
+
+/**
+ * Class _AuditableChild5 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 _AuditableChild5 extends PersistentObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final SelfProperty<AuditableChild5> SELF = PropertyFactory.createSelf(AuditableChild5.class);
+
+ public static final String ID_PK_COLUMN = "ID";
+
+ public static final StringProperty<String> CHAR_PROPERTY1 = PropertyFactory.createString("charProperty1", String.class);
+ public static final EntityProperty<Auditable5> PARENT = PropertyFactory.createEntity("parent", Auditable5.class);
+
+ protected String charProperty1;
+
+ protected Object parent;
+
+ public void setCharProperty1(String charProperty1) {
+ beforePropertyWrite("charProperty1", this.charProperty1, charProperty1);
+ this.charProperty1 = charProperty1;
+ }
+
+ public String getCharProperty1() {
+ beforePropertyRead("charProperty1");
+ return this.charProperty1;
+ }
+
+ public void setParent(Auditable5 parent) {
+ setToOneTarget("parent", parent, true);
+ }
+
+ public Auditable5 getParent() {
+ return (Auditable5)readProperty("parent");
+ }
+
+ @Override
+ public Object readPropertyDirectly(String propName) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch(propName) {
+ case "charProperty1":
+ return this.charProperty1;
+ case "parent":
+ return this.parent;
+ default:
+ return super.readPropertyDirectly(propName);
+ }
+ }
+
+ @Override
+ public void writePropertyDirectly(String propName, Object val) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (propName) {
+ case "charProperty1":
+ this.charProperty1 = (String)val;
+ break;
+ case "parent":
+ this.parent = 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.charProperty1);
+ out.writeObject(this.parent);
+ }
+
+ @Override
+ protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ super.readState(in);
+ this.charProperty1 = (String)in.readObject();
+ this.parent = in.readObject();
+ }
+
+}
diff --git a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/unit/AuditableRuntimeCase.java b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/unit/AuditableRuntimeCase.java
index c86b7e1..cbb3e1b 100644
--- a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/unit/AuditableRuntimeCase.java
+++ b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/unit/AuditableRuntimeCase.java
@@ -42,6 +42,9 @@
protected TableHelper auditable3;
protected TableHelper auditable4;
+ protected TableHelper auditable5;
+ protected TableHelper auditableChild5;
+
protected TableHelper auditLog;
@Before
@@ -68,6 +71,10 @@
this.auditable4 = new TableHelper(dbHelper, "AUDITABLE4").setColumns("ID", "CHAR_PROPERTY1", "CHAR_PROPERTY2",
"AUDITABLE3_ID");
+ this.auditable5 = new TableHelper(dbHelper, "AUDITABLE5").setColumns("ID", "CHAR_PROPERTY1");
+ this.auditableChild5 = new TableHelper(dbHelper, "AUDITABLE_CHILD5").setColumns("ID", "AUDITABLE5_ID",
+ "CHAR_PROPERTY1");
+
this.auditableChild1.deleteAll();
this.auditableChild1x.deleteAll();
this.auditable1.deleteAll();
@@ -75,6 +82,8 @@
this.auditable2.deleteAll();
this.auditable4.deleteAll();
this.auditable3.deleteAll();
+ this.auditableChild5.deleteAll();
+ this.auditable5.deleteAll();
this.auditLog.deleteAll();
}
diff --git a/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml b/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml
index cbcba1c..179bbd8 100644
--- a/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml
+++ b/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml
@@ -24,6 +24,10 @@
<db-attribute name="CHAR_PROPERTY2" type="VARCHAR" length="200"/>
<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
</db-entity>
+ <db-entity name="AUDITABLE5">
+ <db-attribute name="CHAR_PROPERTY1" type="VARCHAR" length="200"/>
+ <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ </db-entity>
<db-entity name="AUDITABLE_CHILD1">
<db-attribute name="AUDITABLE1_ID" type="INTEGER"/>
<db-attribute name="CHAR_PROPERTY1" type="VARCHAR" length="200"/>
@@ -40,6 +44,11 @@
<db-attribute name="CHAR_PROPERTY2" type="VARCHAR" length="200"/>
<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
</db-entity>
+ <db-entity name="AUDITABLE_CHILD5">
+ <db-attribute name="AUDITABLE5_ID" type="INTEGER"/>
+ <db-attribute name="CHAR_PROPERTY1" type="VARCHAR" length="200"/>
+ <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ </db-entity>
<db-entity name="AUDIT_LOG">
<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
<db-attribute name="LOG" type="CLOB"/>
@@ -78,6 +87,9 @@
<obj-attribute name="charProperty1" type="java.lang.String" db-attribute-path="CHAR_PROPERTY1"/>
<obj-attribute name="charProperty2" type="java.lang.String" db-attribute-path="CHAR_PROPERTY2"/>
</obj-entity>
+ <obj-entity name="Auditable5" className="org.apache.cayenne.commitlog.db.Auditable5" dbEntityName="AUDITABLE5">
+ <obj-attribute name="charProperty1" type="java.lang.String" db-attribute-path="CHAR_PROPERTY1"/>
+ </obj-entity>
<obj-entity name="AuditableChild1" className="org.apache.cayenne.commitlog.db.AuditableChild1" dbEntityName="AUDITABLE_CHILD1">
<obj-attribute name="charProperty1" type="java.lang.String" db-attribute-path="CHAR_PROPERTY1"/>
</obj-entity>
@@ -88,6 +100,9 @@
<obj-attribute name="charProperty1" type="java.lang.String" db-attribute-path="CHAR_PROPERTY1"/>
<obj-attribute name="charProperty2" type="java.lang.String" db-attribute-path="CHAR_PROPERTY2"/>
</obj-entity>
+ <obj-entity name="AuditableChild5" className="org.apache.cayenne.commitlog.db.AuditableChild5" dbEntityName="AUDITABLE_CHILD5">
+ <obj-attribute name="charProperty1" type="java.lang.String" db-attribute-path="CHAR_PROPERTY1"/>
+ </obj-entity>
<obj-entity name="E1" className="org.apache.cayenne.commitlog.db.E1" dbEntityName="E1"/>
<obj-entity name="E2" className="org.apache.cayenne.commitlog.db.E2" dbEntityName="E2"/>
<obj-entity name="E3" className="org.apache.cayenne.commitlog.db.E3" dbEntityName="E3"/>
@@ -107,6 +122,9 @@
<db-relationship name="auditable3" source="AUDITABLE4" target="AUDITABLE3">
<db-attribute-pair source="AUDITABLE3_ID" target="ID"/>
</db-relationship>
+ <db-relationship name="children" source="AUDITABLE5" target="AUDITABLE_CHILD5" toMany="true">
+ <db-attribute-pair source="ID" target="AUDITABLE5_ID"/>
+ </db-relationship>
<db-relationship name="parent" source="AUDITABLE_CHILD1" target="AUDITABLE1">
<db-attribute-pair source="AUDITABLE1_ID" target="ID"/>
</db-relationship>
@@ -116,6 +134,9 @@
<db-relationship name="parent" source="AUDITABLE_CHILD3" target="AUDITABLE2">
<db-attribute-pair source="AUDITABLE2_ID" target="ID"/>
</db-relationship>
+ <db-relationship name="parent" source="AUDITABLE_CHILD5" target="AUDITABLE5">
+ <db-attribute-pair source="AUDITABLE5_ID" target="ID"/>
+ </db-relationship>
<db-relationship name="e34s" source="E3" target="E34" toDependentPK="true" toMany="true">
<db-attribute-pair source="ID" target="E3_ID"/>
</db-relationship>
@@ -132,9 +153,11 @@
<obj-relationship name="children" source="Auditable2" target="AuditableChild3" deleteRule="Deny" db-relationship-path="children"/>
<obj-relationship name="auditable4s" source="Auditable3" target="Auditable4" deleteRule="Deny" db-relationship-path="auditable4s"/>
<obj-relationship name="auditable3" source="Auditable4" target="Auditable3" deleteRule="Nullify" db-relationship-path="auditable3"/>
+ <obj-relationship name="children" source="Auditable5" target="AuditableChild5" deleteRule="Deny" db-relationship-path="children"/>
<obj-relationship name="parent" source="AuditableChild1" target="Auditable1" deleteRule="Nullify" db-relationship-path="parent"/>
<obj-relationship name="parent" source="AuditableChild1x" target="Auditable1" deleteRule="Nullify" db-relationship-path="parent"/>
<obj-relationship name="parent" source="AuditableChild3" target="Auditable2" deleteRule="Nullify" db-relationship-path="parent"/>
+ <obj-relationship name="parent" source="AuditableChild5" target="Auditable5" deleteRule="Nullify" db-relationship-path="parent"/>
<obj-relationship name="e4s" source="E3" target="E4" deleteRule="Deny" db-relationship-path="e34s.e4"/>
<obj-relationship name="e3s" source="E4" target="E3" deleteRule="Deny" db-relationship-path="e34s.e3"/>
<cgen xmlns="http://cayenne.apache.org/schema/11/cgen">
@@ -142,6 +165,10 @@
<mode>entity</mode>
<template>templates/v4_1/subclass.vm</template>
<superTemplate>templates/v4_1/superclass.vm</superTemplate>
+ <embeddableTemplate>templates/v4_1/embeddable-subclass.vm</embeddableTemplate>
+ <embeddableSuperTemplate>templates/v4_1/embeddable-superclass.vm</embeddableSuperTemplate>
+ <queryTemplate>templates/v4_1/datamap-subclass.vm</queryTemplate>
+ <querySuperTemplate>templates/v4_1/datamap-superclass.vm</querySuperTemplate>
<outputPattern>*.java</outputPattern>
<makePairs>true</makePairs>
<usePkgPath>true</usePkgPath>