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 2010/06/05 03:09:44 UTC
svn commit: r951630 - in
/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test:
java/org/apache/cayenne/access/
java/org/apache/cayenne/testdo/inheritance/vertical/auto/ resources/
Author: aadamchik
Date: Sat Jun 5 01:09:43 2010
New Revision: 951630
URL: http://svn.apache.org/viewvc?rev=951630&view=rev
Log:
CAY-1090 vertical inheritance
(implementing via common root + flattened attributes)
* select unit tests
* insert unit tests
* delete unit tests
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/VerticalInheritanceTest.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/inheritance/vertical/auto/_IvRoot.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/inheritance-vertical.map.xml
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/VerticalInheritanceTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/VerticalInheritanceTest.java?rev=951630&r1=951629&r2=951630&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/VerticalInheritanceTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/VerticalInheritanceTest.java Sat Jun 5 01:09:43 2010
@@ -18,10 +18,18 @@
****************************************************************/
package org.apache.cayenne.access;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.query.SelectQuery;
import org.apache.cayenne.test.DBHelper;
import org.apache.cayenne.test.TableHelper;
import org.apache.cayenne.testdo.inheritance.vertical.IvRoot;
+import org.apache.cayenne.testdo.inheritance.vertical.IvSub1;
+import org.apache.cayenne.testdo.inheritance.vertical.IvSub1Sub1;
+import org.apache.cayenne.testdo.inheritance.vertical.IvSub2;
import org.apache.cayenne.unit.AccessStack;
import org.apache.cayenne.unit.CayenneCase;
import org.apache.cayenne.unit.CayenneResources;
@@ -33,11 +41,130 @@ public class VerticalInheritanceTest ext
return CayenneResources.getResources().getAccessStack("InheritanceVerticalStack");
}
- public void testSelectQuery() throws Exception {
+ public void testInsert_Root() throws Exception {
+ DBHelper dbHelper = getDbHelper();
+
+ TableHelper ivRootTable = new TableHelper(dbHelper, "IV_ROOT");
+ ivRootTable.setColumns("ID", "NAME", "DISCRIMINATOR");
+ ivRootTable.deleteAll();
+
+ assertEquals(0, ivRootTable.getRowCount());
+
+ IvRoot root = createDataContext().newObject(IvRoot.class);
+ root.setName("XyZ");
+ root.getObjectContext().commitChanges();
+
+ assertEquals(1, ivRootTable.getRowCount());
+
+ Object[] rootData = ivRootTable.select();
+ assertEquals(3, rootData.length);
+ assertTrue(rootData[0] instanceof Number);
+ assertTrue(((Number) rootData[0]).intValue() > 0);
+ assertEquals("XyZ", rootData[1]);
+ assertNull(rootData[2]);
+ }
+
+ public void testInsert_Sub1() throws Exception {
+ DBHelper dbHelper = getDbHelper();
+
+ TableHelper ivRootTable = new TableHelper(dbHelper, "IV_ROOT");
+ ivRootTable.setColumns("ID", "NAME", "DISCRIMINATOR");
+
+ TableHelper ivSub1Table = new TableHelper(dbHelper, "IV_SUB1");
+ ivSub1Table.setColumns("ID", "SUB1_NAME");
+
+ ivSub1Table.deleteAll();
+ ivRootTable.deleteAll();
+
+ IvSub1 sub1 = createDataContext().newObject(IvSub1.class);
+ sub1.setName("XyZX");
+ sub1.getObjectContext().commitChanges();
+
+ assertEquals(1, ivRootTable.getRowCount());
+ assertEquals(1, ivSub1Table.getRowCount());
+
+ Object[] data = ivRootTable.select();
+ assertEquals(3, data.length);
+ assertTrue(data[0] instanceof Number);
+ assertTrue(((Number) data[0]).intValue() > 0);
+ assertEquals("XyZX", data[1]);
+ assertEquals("IvSub1", data[2]);
+
+ Object[] subdata = ivSub1Table.select();
+ assertEquals(2, subdata.length);
+ assertEquals(data[0], subdata[0]);
+ assertNull(subdata[1]);
+
+ ivSub1Table.deleteAll();
+ ivRootTable.deleteAll();
+
+ IvSub1 sub11 = createDataContext().newObject(IvSub1.class);
+ sub11.setName("XyZXY");
+ sub11.setSub1Name("BdE2");
+ sub11.getObjectContext().commitChanges();
+
+ data = ivRootTable.select();
+ assertEquals(3, data.length);
+ assertTrue(data[0] instanceof Number);
+ assertTrue(((Number) data[0]).intValue() > 0);
+ assertEquals("XyZXY", data[1]);
+ assertEquals("IvSub1", data[2]);
+
+ subdata = ivSub1Table.select();
+ assertEquals(2, subdata.length);
+ assertEquals(data[0], subdata[0]);
+ assertEquals("BdE2", subdata[1]);
+ }
+
+ public void testInsert_Sub1Sub1() throws Exception {
+ DBHelper dbHelper = getDbHelper();
+
+ TableHelper ivRootTable = new TableHelper(dbHelper, "IV_ROOT");
+ ivRootTable.setColumns("ID", "NAME", "DISCRIMINATOR");
+
+ TableHelper ivSub1Table = new TableHelper(dbHelper, "IV_SUB1");
+ ivSub1Table.setColumns("ID", "SUB1_NAME");
+
+ TableHelper ivSub1Sub1Table = new TableHelper(dbHelper, "IV_SUB1_SUB1");
+ ivSub1Sub1Table.setColumns("ID", "SUB1_SUB1_NAME");
+
+ ivSub1Sub1Table.deleteAll();
+ ivSub1Table.deleteAll();
+ ivRootTable.deleteAll();
+
+ IvSub1Sub1 sub1Sub1 = createDataContext().newObject(IvSub1Sub1.class);
+ sub1Sub1.setName("XyZN");
+ sub1Sub1.setSub1Name("mDA");
+ sub1Sub1.setSub1Sub1Name("3DQa");
+ sub1Sub1.getObjectContext().commitChanges();
+
+ assertEquals(1, ivRootTable.getRowCount());
+ assertEquals(1, ivSub1Table.getRowCount());
+ assertEquals(1, ivSub1Sub1Table.getRowCount());
+
+ Object[] data = ivRootTable.select();
+ assertEquals(3, data.length);
+ assertTrue(data[0] instanceof Number);
+ assertTrue(((Number) data[0]).intValue() > 0);
+ assertEquals("XyZN", data[1]);
+ assertEquals("IvSub1Sub1", data[2]);
+
+ Object[] subdata = ivSub1Table.select();
+ assertEquals(2, subdata.length);
+ assertEquals(data[0], subdata[0]);
+ assertEquals("mDA", subdata[1]);
+
+ Object[] subsubdata = ivSub1Sub1Table.select();
+ assertEquals(2, subsubdata.length);
+ assertEquals(data[0], subsubdata[0]);
+ assertEquals("3DQa", subsubdata[1]);
+ }
+
+ public void testSelectQuery_SuperSub() throws Exception {
DBHelper dbHelper = getDbHelper();
TableHelper ivRootTable = new TableHelper(dbHelper, "IV_ROOT");
- ivRootTable.setColumns("ID", "NAME");
+ ivRootTable.setColumns("ID", "NAME", "DISCRIMINATOR");
TableHelper ivSub1Table = new TableHelper(dbHelper, "IV_SUB1");
ivSub1Table.setColumns("ID", "SUB1_NAME");
@@ -47,13 +174,234 @@ public class VerticalInheritanceTest ext
ivRootTable.deleteAll();
// insert
- ivRootTable.insert(1, "xROOT");
- ivRootTable.insert(2, "xSUB1_ROOT");
+ ivRootTable.insert(1, "xROOT", null);
+ ivRootTable.insert(2, "xSUB1_ROOT", "IvSub1");
ivSub1Table.insert(2, "xSUB1");
SelectQuery query = new SelectQuery(IvRoot.class);
- // List<IvRoot> results = createDataContext().performQuery(query);
+ List<IvRoot> results = createDataContext().performQuery(query);
+
+ assertEquals(2, results.size());
+
+ // since we don't have ordering, need to analyze results in an order agnostic
+ // fashion
+ Map<String, IvRoot> resultTypes = new HashMap<String, IvRoot>();
+
+ for (IvRoot result : results) {
+ resultTypes.put(result.getClass().getName(), result);
+ }
+
+ assertEquals(2, resultTypes.size());
+
+ IvRoot root = resultTypes.get(IvRoot.class.getName());
+ assertNotNull(root);
+ assertEquals("xROOT", root.getName());
+ assertNull(root.getDiscriminator());
- // assertEquals(2, results.size());
+ IvSub1 sub1 = (IvSub1) resultTypes.get(IvSub1.class.getName());
+ assertNotNull(sub1);
+ assertEquals("xSUB1_ROOT", sub1.getName());
+ assertEquals("IvSub1", sub1.getDiscriminator());
}
+
+ public void testSelectQuery_DeepAndWide() throws Exception {
+ DBHelper dbHelper = getDbHelper();
+
+ TableHelper ivRootTable = new TableHelper(dbHelper, "IV_ROOT");
+ ivRootTable.setColumns("ID", "NAME", "DISCRIMINATOR");
+
+ TableHelper ivSub1Table = new TableHelper(dbHelper, "IV_SUB1");
+ ivSub1Table.setColumns("ID", "SUB1_NAME");
+
+ TableHelper ivSub2Table = new TableHelper(dbHelper, "IV_SUB2");
+ ivSub2Table.setColumns("ID", "SUB2_NAME");
+
+ TableHelper ivSub1Sub1Table = new TableHelper(dbHelper, "IV_SUB1_SUB1");
+ ivSub1Sub1Table.setColumns("ID", "SUB1_SUB1_NAME");
+
+ // delete
+ ivSub1Sub1Table.deleteAll();
+ ivSub2Table.deleteAll();
+ ivSub1Table.deleteAll();
+ ivRootTable.deleteAll();
+
+ // insert
+ ivRootTable.insert(1, "xROOT", null);
+
+ ivRootTable.insert(2, "xSUB1_ROOT", "IvSub1");
+ ivSub1Table.insert(2, "xSUB1");
+
+ ivRootTable.insert(3, "xSUB1_SUB1_ROOT", "IvSub1Sub1");
+ ivSub1Table.insert(3, "xSUB1_SUB1_SUBROOT");
+ ivSub1Sub1Table.insert(3, "xSUB1_SUB1");
+
+ ivRootTable.insert(4, "xROOT_SUB2", "IvSub2");
+ ivSub2Table.insert(4, "xSUB2");
+
+ SelectQuery query = new SelectQuery(IvRoot.class);
+ List<IvRoot> results = createDataContext().performQuery(query);
+
+ assertEquals(4, results.size());
+
+ // since we don't have ordering, need to analyze results in an order agnostic
+ // fashion
+ Map<String, IvRoot> resultTypes = new HashMap<String, IvRoot>();
+
+ for (IvRoot result : results) {
+ resultTypes.put(result.getClass().getName(), result);
+ }
+
+ assertEquals(4, resultTypes.size());
+
+ IvRoot root = resultTypes.get(IvRoot.class.getName());
+ assertNotNull(root);
+ assertEquals("xROOT", root.getName());
+ assertNull(root.getDiscriminator());
+
+ IvSub1 sub1 = (IvSub1) resultTypes.get(IvSub1.class.getName());
+ assertNotNull(sub1);
+ assertEquals("xSUB1_ROOT", sub1.getName());
+ assertEquals("IvSub1", sub1.getDiscriminator());
+
+ IvSub1Sub1 sub1Sub1 = (IvSub1Sub1) resultTypes.get(IvSub1Sub1.class.getName());
+ assertNotNull(sub1Sub1);
+ assertEquals("xSUB1_SUB1_ROOT", sub1Sub1.getName());
+ assertEquals("IvSub1Sub1", sub1Sub1.getDiscriminator());
+ assertEquals("xSUB1_SUB1_SUBROOT", sub1Sub1.getSub1Name());
+ assertEquals("xSUB1_SUB1", sub1Sub1.getSub1Sub1Name());
+
+ IvSub2 sub2 = (IvSub2) resultTypes.get(IvSub2.class.getName());
+ assertNotNull(sub2);
+ assertEquals("xROOT_SUB2", sub2.getName());
+ assertEquals("IvSub2", sub2.getDiscriminator());
+ assertEquals("xSUB2", sub2.getSub2Name());
+ }
+
+ public void testSelectQuery_MiddleLeaf() throws Exception {
+ DBHelper dbHelper = getDbHelper();
+
+ TableHelper ivRootTable = new TableHelper(dbHelper, "IV_ROOT");
+ ivRootTable.setColumns("ID", "NAME", "DISCRIMINATOR");
+
+ TableHelper ivSub1Table = new TableHelper(dbHelper, "IV_SUB1");
+ ivSub1Table.setColumns("ID", "SUB1_NAME");
+
+ TableHelper ivSub2Table = new TableHelper(dbHelper, "IV_SUB2");
+ ivSub2Table.setColumns("ID", "SUB2_NAME");
+
+ TableHelper ivSub1Sub1Table = new TableHelper(dbHelper, "IV_SUB1_SUB1");
+ ivSub1Sub1Table.setColumns("ID", "SUB1_SUB1_NAME");
+
+ // delete
+ ivSub1Sub1Table.deleteAll();
+ ivSub2Table.deleteAll();
+ ivSub1Table.deleteAll();
+ ivRootTable.deleteAll();
+
+ // insert
+ ivRootTable.insert(1, "xROOT", null);
+
+ ivRootTable.insert(2, "xSUB1_ROOT", "IvSub1");
+ ivSub1Table.insert(2, "xSUB1");
+
+ ivRootTable.insert(3, "xSUB1_SUB1_ROOT", "IvSub1Sub1");
+ ivSub1Table.insert(3, "xSUB1_SUB1_SUBROOT");
+ ivSub1Sub1Table.insert(3, "xSUB1_SUB1");
+
+ ivRootTable.insert(4, "xROOT_SUB2", "IvSub2");
+ ivSub2Table.insert(4, "xSUB2");
+
+ SelectQuery query = new SelectQuery(IvSub1.class);
+ List<IvRoot> results = createDataContext().performQuery(query);
+
+ assertEquals(2, results.size());
+
+ // since we don't have ordering, need to analyze results in an order agnostic
+ // fashion
+ Map<String, IvRoot> resultTypes = new HashMap<String, IvRoot>();
+
+ for (IvRoot result : results) {
+ resultTypes.put(result.getClass().getName(), result);
+ }
+
+ assertEquals(2, resultTypes.size());
+
+ IvSub1 sub1 = (IvSub1) resultTypes.get(IvSub1.class.getName());
+ assertNotNull(sub1);
+ assertEquals("xSUB1_ROOT", sub1.getName());
+ assertEquals("IvSub1", sub1.getDiscriminator());
+
+ IvSub1Sub1 sub1Sub1 = (IvSub1Sub1) resultTypes.get(IvSub1Sub1.class.getName());
+ assertNotNull(sub1Sub1);
+ assertEquals("xSUB1_SUB1_ROOT", sub1Sub1.getName());
+ assertEquals("IvSub1Sub1", sub1Sub1.getDiscriminator());
+ assertEquals("xSUB1_SUB1_SUBROOT", sub1Sub1.getSub1Name());
+ assertEquals("xSUB1_SUB1", sub1Sub1.getSub1Sub1Name());
+ }
+
+ public void testDelete_Mix() throws Exception {
+ DBHelper dbHelper = getDbHelper();
+
+ TableHelper ivRootTable = new TableHelper(dbHelper, "IV_ROOT");
+ ivRootTable.setColumns("ID", "NAME", "DISCRIMINATOR");
+
+ TableHelper ivSub1Table = new TableHelper(dbHelper, "IV_SUB1");
+ ivSub1Table.setColumns("ID", "SUB1_NAME");
+
+ TableHelper ivSub2Table = new TableHelper(dbHelper, "IV_SUB2");
+ ivSub2Table.setColumns("ID", "SUB2_NAME");
+
+ TableHelper ivSub1Sub1Table = new TableHelper(dbHelper, "IV_SUB1_SUB1");
+ ivSub1Sub1Table.setColumns("ID", "SUB1_SUB1_NAME");
+
+ // delete
+ ivSub1Sub1Table.deleteAll();
+ ivSub2Table.deleteAll();
+ ivSub1Table.deleteAll();
+ ivRootTable.deleteAll();
+
+ // insert
+ ivRootTable.insert(1, "xROOT", null);
+
+ ivRootTable.insert(2, "xSUB1_ROOT", "IvSub1");
+ ivSub1Table.insert(2, "xSUB1");
+
+ ivRootTable.insert(3, "xSUB1_SUB1_ROOT", "IvSub1Sub1");
+ ivSub1Table.insert(3, "xSUB1_SUB1_SUBROOT");
+ ivSub1Sub1Table.insert(3, "xSUB1_SUB1");
+
+ ivRootTable.insert(4, "xROOT_SUB2", "IvSub2");
+ ivSub2Table.insert(4, "xSUB2");
+
+ SelectQuery query = new SelectQuery(IvRoot.class);
+
+ ObjectContext context = createDataContext();
+ List<IvRoot> results = context.performQuery(query);
+
+ assertEquals(4, results.size());
+ Map<String, IvRoot> resultTypes = new HashMap<String, IvRoot>();
+
+ for (IvRoot result : results) {
+ resultTypes.put(result.getClass().getName(), result);
+ }
+
+ assertEquals(4, resultTypes.size());
+
+ IvRoot root = resultTypes.get(IvRoot.class.getName());
+ context.deleteObject(root);
+
+ IvSub1 sub1 = (IvSub1) resultTypes.get(IvSub1.class.getName());
+ context.deleteObject(sub1);
+
+ context.commitChanges();
+
+ assertEquals(2, ivRootTable.getRowCount());
+ assertEquals(1, ivSub1Table.getRowCount());
+ assertEquals(1, ivSub1Sub1Table.getRowCount());
+ assertEquals(1, ivSub2Table.getRowCount());
+
+ results = context.performQuery(query);
+ assertEquals(2, results.size());
+ }
+
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/inheritance/vertical/auto/_IvRoot.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/inheritance/vertical/auto/_IvRoot.java?rev=951630&r1=951629&r2=951630&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/inheritance/vertical/auto/_IvRoot.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/inheritance/vertical/auto/_IvRoot.java Sat Jun 5 01:09:43 2010
@@ -10,10 +10,18 @@ import org.apache.cayenne.CayenneDataObj
*/
public abstract class _IvRoot extends CayenneDataObject {
+ public static final String DISCRIMINATOR_PROPERTY = "discriminator";
public static final String NAME_PROPERTY = "name";
public static final String ID_PK_COLUMN = "ID";
+ public void setDiscriminator(String discriminator) {
+ writeProperty("discriminator", discriminator);
+ }
+ public String getDiscriminator() {
+ return (String)readProperty("discriminator");
+ }
+
public void setName(String name) {
writeProperty("name", name);
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/inheritance-vertical.map.xml
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/inheritance-vertical.map.xml?rev=951630&r1=951629&r2=951630&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/inheritance-vertical.map.xml (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/inheritance-vertical.map.xml Sat Jun 5 01:09:43 2010
@@ -5,6 +5,7 @@
project-version="6">
<property name="defaultPackage" value="org.apache.cayenne.testdo.inheritance.vertical"/>
<db-entity name="IV_ROOT">
+ <db-attribute name="DISCRIMINATOR" type="VARCHAR" length="10"/>
<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
<db-attribute name="NAME" type="VARCHAR" length="100"/>
</db-entity>
@@ -22,16 +23,23 @@
<db-attribute name="SUB2_NAME" type="VARCHAR" length="100"/>
</db-entity>
<obj-entity name="IvRoot" className="org.apache.cayenne.testdo.inheritance.vertical.IvRoot" dbEntityName="IV_ROOT">
+ <obj-attribute name="discriminator" type="java.lang.String" db-attribute-path="DISCRIMINATOR"/>
<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
</obj-entity>
- <obj-entity name="IvSub1" superEntityName="IvRoot" className="org.apache.cayenne.testdo.inheritance.vertical.IvSub1" dbEntityName="IV_SUB1">
- <obj-attribute name="sub1Name" type="java.lang.String" db-attribute-path="SUB1_NAME"/>
+ <obj-entity name="IvSub1" superEntityName="IvRoot" className="org.apache.cayenne.testdo.inheritance.vertical.IvSub1" dbEntityName="IV_ROOT">
+ <qualifier><![CDATA[discriminator = "IvSub1"]]></qualifier>
+ <obj-attribute name="sub1Name" type="java.lang.String" db-attribute-path="sub1.SUB1_NAME"/>
+ <attribute-override name="discrimiantor" db-attribute-path="DISCRIMINATOR"/>
+ <attribute-override name="discriminator" db-attribute-path="DISCRIMINATOR"/>
+ <attribute-override name="name" db-attribute-path="NAME"/>
</obj-entity>
- <obj-entity name="IvSub1Sub1" superEntityName="IvSub1" className="org.apache.cayenne.testdo.inheritance.vertical.IvSub1Sub1" dbEntityName="IV_SUB1_SUB1">
- <obj-attribute name="sub1Sub1Name" type="java.lang.String" db-attribute-path="SUB1_SUB1_NAME"/>
+ <obj-entity name="IvSub1Sub1" superEntityName="IvSub1" className="org.apache.cayenne.testdo.inheritance.vertical.IvSub1Sub1" dbEntityName="IV_ROOT">
+ <qualifier><![CDATA[discriminator = "IvSub1Sub1"]]></qualifier>
+ <obj-attribute name="sub1Sub1Name" type="java.lang.String" db-attribute-path="sub1.sub1Sub1.SUB1_SUB1_NAME"/>
</obj-entity>
- <obj-entity name="IvSub2" superEntityName="IvRoot" className="org.apache.cayenne.testdo.inheritance.vertical.IvSub2" dbEntityName="IV_SUB2">
- <obj-attribute name="sub2Name" type="java.lang.String" db-attribute-path="SUB2_NAME"/>
+ <obj-entity name="IvSub2" superEntityName="IvRoot" className="org.apache.cayenne.testdo.inheritance.vertical.IvSub2" dbEntityName="IV_ROOT">
+ <qualifier><![CDATA[discriminator = "IvSub2"]]></qualifier>
+ <obj-attribute name="sub2Name" type="java.lang.String" db-attribute-path="sub2.SUB2_NAME"/>
</obj-entity>
<db-relationship name="sub1" source="IV_ROOT" target="IV_SUB1" toDependentPK="true" toMany="false">
<db-attribute-pair source="ID" target="ID"/>