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 2011/03/25 14:42:57 UTC

svn commit: r1085359 - in /cayenne/main/trunk: docs/doc/src/main/resources/ framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/ framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/ framework/caye...

Author: aadamchik
Date: Fri Mar 25 13:42:56 2011
New Revision: 1085359

URL: http://svn.apache.org/viewvc?rev=1085359&view=rev
Log:
CAY-1553 cayenne-lifecycle: @SortWeight annotation

Added:
    cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/
    cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/SortWeight.java
    cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorter.java
    cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortDep.java
    cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortRoot.java
    cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortDep.java
    cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortRoot.java
    cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/
    cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorterTest.java
Modified:
    cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
    cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/UuidRelationshipFilter.java
    cayenne/main/trunk/framework/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml

Modified: cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt?rev=1085359&r1=1085358&r2=1085359&view=diff
==============================================================================
--- cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt (original)
+++ cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt Fri Mar 25 13:42:56 2011
@@ -17,6 +17,7 @@ CAY-1544 Remove jdk1.6 module from Cayen
 CAY-1545 cayenne-lifecycle Referenceable handler refactoring
 CAY-1547 cayenne-lifecycle: support for setting UuidRelationships
 CAY-1549 Migrate BatchQueryBuilderFactory to DI
+CAY-1553 cayenne-lifecycle: @SortWeight annotation 
 
 Bug Fixes Since 3.1M2:
 

Modified: cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/UuidRelationshipFilter.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/UuidRelationshipFilter.java?rev=1085359&r1=1085358&r2=1085359&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/UuidRelationshipFilter.java (original)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/UuidRelationshipFilter.java Fri Mar 25 13:42:56 2011
@@ -30,6 +30,8 @@ import org.apache.cayenne.annotation.Pos
 import org.apache.cayenne.annotation.PostPersist;
 import org.apache.cayenne.annotation.PostUpdate;
 import org.apache.cayenne.graph.GraphDiff;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.query.Query;
 
 /**
@@ -43,6 +45,29 @@ public class UuidRelationshipFilter impl
 
     public void init(DataChannel channel) {
         this.faultingStrategy = createFaultingStrategy();
+        registerUuidRelationships(channel);
+    }
+
+    protected void registerUuidRelationships(DataChannel channel) {
+
+        // TODO: create a DI-managed chain of mapping post processors, and extract this
+        // code to a UuidRelationshipModule. The following code in DataDomainProvider
+        // should be in the standard chain, and this method code - in an extension
+        // dataDomain.getEntityResolver().applyDBLayerDefaults();
+        // dataDomain.getEntityResolver().applyObjectLayerDefaults();
+
+        EntityResolver resolver = channel.getEntityResolver();
+        for (ObjEntity entity : resolver.getObjEntities()) {
+
+            Class<?> type = resolver
+                    .getClassDescriptor(entity.getName())
+                    .getObjectClass();
+            
+            UuidRelationship a = type.getAnnotation(UuidRelationship.class);
+            if(a != null) {
+                
+            }
+        }
     }
 
     protected UuidRelationshipFaultingStrategy createFaultingStrategy() {

Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/SortWeight.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/SortWeight.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/SortWeight.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/SortWeight.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,47 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+package org.apache.cayenne.lifecycle.sort;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation that defines the insertion sorting "weight" of an entity that is used
+ * when sorting DB operations. This annotation allows to override the topological sorting
+ * algorithm used by Cayenne by default in special occasions.
+ * 
+ * @since 3.1
+ */
+@Target( {
+    ElementType.TYPE
+})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SortWeight {
+
+    /**
+     * Returns the "weight" of the entity used for the purpose of the DB operations
+     * sorting. Entities with lower values will be inserted before entities with higher
+     * values. The opposite is true for the delete operations.
+     */
+    int value() default 1;
+}

Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorter.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorter.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorter.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorter.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,116 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+package org.apache.cayenne.lifecycle.sort;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cayenne.ashwood.AshwoodEntitySorter;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.commons.collections.comparators.ReverseComparator;
+
+/**
+ * EntitySorter that takes into account entity "weights", and otherwise delegating to
+ * another (topological) sorter.
+ * 
+ * @since 3.1
+ */
+public class WeightedAshwoodEntitySorter extends AshwoodEntitySorter {
+
+    private Comparator<DbEntity> weightedDbEntityComparator;
+    private Comparator<ObjEntity> weightedObjEntityComparator;
+
+    private Map<DbEntity, Integer> entityWeights;
+
+    public WeightedAshwoodEntitySorter() {
+        this.weightedDbEntityComparator = new WeightedDbEntityComparator();
+        this.weightedObjEntityComparator = new WeightedObjEntityComparator();
+        this.entityWeights = Collections.EMPTY_MAP;
+    }
+
+    @Override
+    protected void doIndexSorter() {
+        super.doIndexSorter();
+
+        entityWeights = new HashMap<DbEntity, Integer>();
+
+        for (ObjEntity entity : entityResolver.getObjEntities()) {
+
+            Class<?> type = entityResolver
+                    .getClassDescriptor(entity.getName())
+                    .getObjectClass();
+            SortWeight weight = type.getAnnotation(SortWeight.class);
+            if (weight != null) {
+                entityWeights.put(entity.getDbEntity(), weight.value());
+            }
+        }
+    }
+
+    @Override
+    protected Comparator<DbEntity> getDbEntityComparator(boolean dependantFirst) {
+        Comparator<DbEntity> c = weightedDbEntityComparator;
+        if (dependantFirst) {
+            c = new ReverseComparator(c);
+        }
+        return c;
+    }
+
+    @Override
+    protected Comparator<ObjEntity> getObjEntityComparator(boolean dependantFirst) {
+        Comparator<ObjEntity> c = weightedObjEntityComparator;
+        if (dependantFirst) {
+            c = new ReverseComparator(c);
+        }
+        return c;
+    }
+
+    private int getWeight(DbEntity e) {
+        Integer w = entityWeights.get(e);
+        return w != null ? w.intValue() : 1;
+    }
+
+    private final class WeightedDbEntityComparator implements Comparator<DbEntity> {
+
+        public int compare(DbEntity t1, DbEntity t2) {
+            if (t1 == t2) {
+                return 0;
+            }
+
+            int delta = getWeight(t1) - getWeight(t2);
+            return delta != 0 ? delta : dbEntityComparator.compare(t1, t2);
+        }
+    }
+
+    private final class WeightedObjEntityComparator implements Comparator<ObjEntity> {
+
+        public int compare(ObjEntity o1, ObjEntity o2) {
+            if (o1 == o2) {
+                return 0;
+            }
+
+            DbEntity t1 = o1.getDbEntity();
+            DbEntity t2 = o2.getDbEntity();
+
+            return weightedDbEntityComparator.compare(t1, t2);
+        }
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortDep.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortDep.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortDep.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortDep.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,7 @@
+package org.apache.cayenne.lifecycle.db;
+
+import org.apache.cayenne.lifecycle.db.auto._SortDep;
+
+public class SortDep extends _SortDep {
+
+}

Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortRoot.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortRoot.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortRoot.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortRoot.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,9 @@
+package org.apache.cayenne.lifecycle.db;
+
+import org.apache.cayenne.lifecycle.db.auto._SortRoot;
+import org.apache.cayenne.lifecycle.sort.SortWeight;
+
+@SortWeight(2)
+public class SortRoot extends _SortRoot {
+
+}

Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortDep.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortDep.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortDep.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortDep.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,27 @@
+package org.apache.cayenne.lifecycle.db.auto;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.lifecycle.db.SortRoot;
+
+/**
+ * Class _SortDep 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 _SortDep extends CayenneDataObject {
+
+    public static final String ROOT_PROPERTY = "root";
+
+    public static final String ID_PK_COLUMN = "ID";
+
+    public void setRoot(SortRoot root) {
+        setToOneTarget("root", root, true);
+    }
+
+    public SortRoot getRoot() {
+        return (SortRoot)readProperty("root");
+    }
+
+
+}

Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortRoot.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortRoot.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortRoot.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortRoot.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,32 @@
+package org.apache.cayenne.lifecycle.db.auto;
+
+import java.util.List;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.lifecycle.db.SortDep;
+
+/**
+ * Class _SortRoot 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 _SortRoot extends CayenneDataObject {
+
+    public static final String DEPS_PROPERTY = "deps";
+
+    public static final String ID_PK_COLUMN = "ID";
+
+    public void addToDeps(SortDep obj) {
+        addToManyTarget("deps", obj, true);
+    }
+    public void removeFromDeps(SortDep obj) {
+        removeToManyTarget("deps", obj, true);
+    }
+    @SuppressWarnings("unchecked")
+    public List<SortDep> getDeps() {
+        return (List<SortDep>)readProperty("deps");
+    }
+
+
+}

Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorterTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorterTest.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorterTest.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorterTest.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,79 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+package org.apache.cayenne.lifecycle.sort;
+
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.lifecycle.relationship.UuidRelationshipFilter;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.EntityResolver;
+
+public class WeightedAshwoodEntitySorterTest extends TestCase {
+
+    private ServerRuntime runtime;
+
+    @Override
+    protected void setUp() throws Exception {
+
+        runtime = new ServerRuntime("cayenne-lifecycle.xml");
+
+        // a filter is required to invalidate root objects after commit
+        UuidRelationshipFilter filter = new UuidRelationshipFilter();
+        runtime.getDataDomain().addFilter(filter);
+        runtime.getDataDomain().getEntityResolver().getCallbackRegistry().addListener(
+                filter);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        runtime.shutdown();
+    }
+
+    public void testSortDbEntities() {
+
+        EntityResolver resolver = runtime.getDataDomain().getEntityResolver();
+
+        // since it is impossible to ensure non-coincidental sort order of unrelated
+        // DbEntities (without overriding DbEntity.hashCode()), we'll test on 2 entities
+        // with a relationship, and reverse the topological order with SortWeight
+        // annotation.
+
+        List<DbEntity> eSorted = Arrays.asList(resolver.getDbEntity("SORT_DEP"), resolver
+                .getDbEntity("SORT_ROOT"));
+
+        List<DbEntity> e1 = Arrays.asList(resolver.getDbEntity("SORT_ROOT"), resolver
+                .getDbEntity("SORT_DEP"));
+
+        List<DbEntity> e2 = Arrays.asList(resolver.getDbEntity("SORT_DEP"), resolver
+                .getDbEntity("SORT_ROOT"));
+
+        WeightedAshwoodEntitySorter sorter = new WeightedAshwoodEntitySorter();
+        sorter.setEntityResolver(resolver);
+
+        sorter.sortDbEntities(e1, false);
+        assertEquals(eSorted, e1);
+
+        sorter.sortDbEntities(e2, false);
+        assertEquals(eSorted, e2);
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml?rev=1085359&r1=1085358&r2=1085359&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml (original)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml Fri Mar 25 13:42:56 2011
@@ -10,6 +10,13 @@
 	<db-entity name="E2">
 		<db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
 	</db-entity>
+	<db-entity name="SORT_DEP">
+		<db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="ROOT_ID" type="BIGINT" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="SORT_ROOT">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
 	<db-entity name="UUID_ROOT1">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="UUID" type="VARCHAR" length="200"/>
@@ -18,7 +25,19 @@
 	</obj-entity>
 	<obj-entity name="E2" className="org.apache.cayenne.lifecycle.db.E2" dbEntityName="E2">
 	</obj-entity>
+	<obj-entity name="SortDep" className="org.apache.cayenne.lifecycle.db.SortDep" dbEntityName="SORT_DEP">
+	</obj-entity>
+	<obj-entity name="SortRoot" className="org.apache.cayenne.lifecycle.db.SortRoot" dbEntityName="SORT_ROOT">
+	</obj-entity>
 	<obj-entity name="UuidRoot1" className="org.apache.cayenne.lifecycle.db.UuidRoot1" dbEntityName="UUID_ROOT1">
 		<obj-attribute name="uuid" type="java.lang.String" db-attribute-path="UUID"/>
 	</obj-entity>
+	<db-relationship name="root" source="SORT_DEP" target="SORT_ROOT" toMany="false">
+		<db-attribute-pair source="ROOT_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="deps" source="SORT_ROOT" target="SORT_DEP" toMany="true">
+		<db-attribute-pair source="ID" target="ROOT_ID"/>
+	</db-relationship>
+	<obj-relationship name="root" source="SortDep" target="SortRoot" deleteRule="Nullify" db-relationship-path="root"/>
+	<obj-relationship name="deps" source="SortRoot" target="SortDep" deleteRule="Deny" db-relationship-path="deps"/>
 </data-map>