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 2009/09/07 22:50:02 UTC
svn commit: r812273 - in
/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne:
access/HierarchicalObjectResolverNode.java
access/ResultScanParentAttachmentStrategy.java
query/SelectQueryPrefetchRouterAction.java
Author: aadamchik
Date: Mon Sep 7 20:50:02 2009
New Revision: 812273
URL: http://svn.apache.org/viewvc?rev=812273&view=rev
Log:
CAY-1250 Prefetching doesn't work with prefetched subentity
adding ResultScanParentAttachmentStrategy
Added:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultScanParentAttachmentStrategy.java
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java?rev=812273&r1=812272&r2=812273&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java Mon Sep 7 20:50:02 2009
@@ -40,10 +40,16 @@
if (node.getParent() == null || node.getParent().isPhantom()) {
this.parentAttachmentStrategy = new NoopParentAttachmentStrategy();
}
- else {
+ else if (node
+ .getIncoming()
+ .getRelationship()
+ .isSourceIndependentFromTargetChange()) {
this.parentAttachmentStrategy = new JoinedIdParentAttachementStrategy(context
.getGraphManager(), node);
}
+ else {
+ this.parentAttachmentStrategy = new ResultScanParentAttachmentStrategy(node);
+ }
}
@Override
@@ -58,7 +64,7 @@
// here we can get the same object repeated multiple times in case of
// many-to-many between prefetched and main entity... this is needed to
// connect prefetched objects to the main objects. To avoid needlessly refreshing
- // the same object multiple times, track which objectids area alrady loaded in
+ // the same object multiple times, track which objectids area already loaded in
// this pass
Map<ObjectId, Persistent> seen = new HashMap<ObjectId, Persistent>();
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultScanParentAttachmentStrategy.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultScanParentAttachmentStrategy.java?rev=812273&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultScanParentAttachmentStrategy.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultScanParentAttachmentStrategy.java Mon Sep 7 20:50:02 2009
@@ -0,0 +1,135 @@
+/*****************************************************************
+ * 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.access;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.DataRow;
+import org.apache.cayenne.Persistent;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjRelationship;
+
+/**
+ * Locates parents by checking for the child PK in the parent DataRow under FK.
+ */
+class ResultScanParentAttachmentStrategy implements ParentAttachmentStrategy {
+
+ private PrefetchProcessorNode parentNode;
+ private DbJoin[] joins;
+ private PrefetchProcessorNode node;
+
+ // TODO: the ivar below makes this strategy STATEFUL and non-reusable. If we need a
+ // stateless version down the line, will need to move this to the
+ // PrefetchProcessorNode.
+ private Map<Object, List<Persistent>> partitionByChild;
+
+ ResultScanParentAttachmentStrategy(PrefetchProcessorNode node) {
+
+ if (node.getParent() == null) {
+ throw new IllegalArgumentException(
+ "ResultScanParentAttachmentStrategy works only for non-root nodes");
+ }
+
+ this.node = node;
+ parentNode = (PrefetchProcessorNode) node.getParent();
+
+ ObjRelationship relationship = node.getIncoming().getRelationship();
+
+ List<DbRelationship> dbRelationships = relationship.getDbRelationships();
+ if (dbRelationships.size() > 1) {
+ throw new IllegalArgumentException(
+ "ResultScanParentAttachmentStrategy does not work for flattened relationships");
+ }
+
+ joins = dbRelationships.get(0).getJoins().toArray(
+ new DbJoin[dbRelationships.get(0).getJoins().size()]);
+
+ }
+
+ public void linkToParent(DataRow row, Persistent object) {
+
+ if (partitionByChild == null) {
+ indexParents();
+ }
+
+ Object key;
+
+ if (joins.length > 1) {
+
+ List<Object> values = new ArrayList<Object>(joins.length);
+
+ for (int j = 0; j < joins.length; j++) {
+ values.add(row.get(joins[j].getTargetName()));
+ }
+
+ key = values;
+ }
+ else {
+ key = row.get(joins[0].getTargetName());
+ }
+
+ List<Persistent> parents = (List<Persistent>) partitionByChild.get(key);
+ if (parents != null) {
+ for (Persistent parent : parents) {
+ node.linkToParent(object, parent);
+ }
+ }
+ }
+
+ private void indexParents() {
+ partitionByChild = new HashMap<Object, List<Persistent>>();
+
+ List<Persistent> objects = parentNode.getObjects();
+ List<DataRow> rows = parentNode.getDataRows();
+ int size = objects.size();
+ for (int i = 0; i < size; i++) {
+
+ DataRow row = rows.get(i);
+
+ Object key;
+
+ if (joins.length > 1) {
+
+ List<Object> values = new ArrayList<Object>(joins.length);
+
+ for (int j = 0; j < joins.length; j++) {
+ values.add(row.get(joins[j].getSourceName()));
+ }
+
+ key = values;
+ }
+ else {
+ key = row.get(joins[0].getSourceName());
+ }
+
+ List<Persistent> parents = partitionByChild.get(key);
+ if (parents == null) {
+ parents = new ArrayList<Persistent>();
+ partitionByChild.put(key, parents);
+ }
+
+ parents.add(objects.get(i));
+ }
+ }
+
+}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java?rev=812273&r1=812272&r2=812273&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java Mon Sep 7 20:50:02 2009
@@ -105,9 +105,12 @@
queryQualifier,
prefetchPath));
- // setup extra result columns to be able to relate result rows to the parent
- // result objects.
- prefetchQuery.addResultPath("db:" + relationship.getReverseDbRelationshipPath());
+ if (relationship.isSourceIndependentFromTargetChange()) {
+ // setup extra result columns to be able to relate result rows to the parent
+ // result objects.
+ prefetchQuery.addResultPath("db:"
+ + relationship.getReverseDbRelationshipPath());
+ }
// pass prefetch subtree to enable joint prefetches...
prefetchQuery.setPrefetchTree(node);