cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aadamc...@apache.org
Subject [1/2] cayenne git commit: CAY-2084 ObjectIdQuery - no cache access polymorphism
Date Thu, 19 May 2016 09:53:40 GMT
Repository: cayenne
Updated Branches:
  refs/heads/master 69ea6e2eb -> 8b63e2d30


CAY-2084 ObjectIdQuery - no cache access polymorphism


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/4d76a54e
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/4d76a54e
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/4d76a54e

Branch: refs/heads/master
Commit: 4d76a54e3361e980803f617871a0053a437d9d46
Parents: 69ea6e2
Author: Andrus Adamchik <andrus@objectstyle.com>
Authored: Thu May 19 10:48:38 2016 +0300
Committer: Andrus Adamchik <andrus@objectstyle.com>
Committed: Thu May 19 12:50:17 2016 +0300

----------------------------------------------------------------------
 .../cayenne/access/DataContextQueryAction.java  |  2 +-
 .../cayenne/access/DataDomainQueryAction.java   | 39 ++++++++-
 .../cayenne/util/ObjectContextQueryAction.java  | 36 +++++++-
 .../DataContextObjectIdQuery_PolymorphicIT.java | 86 ++++++++++++++++++++
 4 files changed, 158 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/4d76a54e/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java
index edd2a7d..948671f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java
@@ -75,7 +75,7 @@ class DataContextQueryAction extends ObjectContextQueryAction {
             ObjectIdQuery oidQuery = (ObjectIdQuery) query;
 
             if (!oidQuery.isFetchMandatory()) {
-                Object object = actingContext.getGraphManager().getNode(
+                Object object = polymorphicObjectFromCache(
                         oidQuery.getObjectId());
                 if (object != null) {
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/4d76a54e/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
index 5ee7531..4f1f9eb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
@@ -42,6 +42,7 @@ import org.apache.cayenne.cache.QueryCacheEntryFactory;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.EntityInheritanceTree;
 import org.apache.cayenne.map.LifecycleEvent;
 import org.apache.cayenne.map.ObjRelationship;
 import org.apache.cayenne.query.EntityResultSegment;
@@ -159,9 +160,9 @@ class DataDomainQueryAction implements QueryRouter, OperationObserver
{
 
             DataRow row = null;
 
-            if (cache != null && !oidQuery.isFetchMandatory()) {
-                row = cache.getCachedSnapshot(oidQuery.getObjectId());
-            }
+			if (cache != null && !oidQuery.isFetchMandatory()) {
+				row = polymorphicRowFromCache(oid);
+			}
 
             // refresh is forced or not found in cache
             if (row == null) {
@@ -181,6 +182,38 @@ class DataDomainQueryAction implements QueryRouter, OperationObserver
{
 
         return !DONE;
     }
+    
+	private DataRow polymorphicRowFromCache(ObjectId superOid) {
+		DataRow row = cache.getCachedSnapshot(superOid);
+		if (row != null) {
+			return row;
+		}
+
+		EntityInheritanceTree inheritanceTree = domain.getEntityResolver().getInheritanceTree(superOid.getEntityName());
+		if (!inheritanceTree.getChildren().isEmpty()) {
+			row = polymorphicRowFromCache(inheritanceTree, superOid.getIdSnapshot());
+		}
+
+		return row;
+	}
+    
+	private DataRow polymorphicRowFromCache(EntityInheritanceTree superNode, Map<String,
?> idSnapshot) {
+
+		for (EntityInheritanceTree child : superNode.getChildren()) {
+			ObjectId id = new ObjectId(child.getEntity().getName(), idSnapshot);
+			DataRow row = cache.getCachedSnapshot(id);
+			if (row != null) {
+				return row;
+			}
+			
+			row = polymorphicRowFromCache(child, idSnapshot);
+			if (row != null) {
+				return row;
+			}
+		}
+
+		return null;
+	}
 
     private boolean interceptRelationshipQuery() {
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/4d76a54e/cayenne-server/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java
b/cayenne-server/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java
index 82a0ae6..41f4a54 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java
@@ -33,6 +33,7 @@ import org.apache.cayenne.Persistent;
 import org.apache.cayenne.QueryResponse;
 import org.apache.cayenne.cache.QueryCache;
 import org.apache.cayenne.cache.QueryCacheEntryFactory;
+import org.apache.cayenne.map.EntityInheritanceTree;
 import org.apache.cayenne.query.ObjectIdQuery;
 import org.apache.cayenne.query.Query;
 import org.apache.cayenne.query.QueryCacheStrategy;
@@ -167,7 +168,7 @@ public abstract class ObjectContextQueryAction {
             ObjectIdQuery oidQuery = (ObjectIdQuery) query;
 
             if (!oidQuery.isFetchMandatory() && !oidQuery.isFetchingDataRows()) {
-                Object object = actingContext.getGraphManager().getNode(
+                Object object = polymorphicObjectFromCache(
                         oidQuery.getObjectId());
                 if (object != null) {
 
@@ -184,6 +185,39 @@ public abstract class ObjectContextQueryAction {
 
         return !DONE;
     }
+    
+    // TODO: bunch of copy/paset from DataDomainQueryAction
+    protected Object polymorphicObjectFromCache(ObjectId superOid) {
+		Object object = actingContext.getGraphManager().getNode(superOid);
+		if (object != null) {
+			return object;
+		}
+
+		EntityInheritanceTree inheritanceTree = actingContext.getEntityResolver().getInheritanceTree(superOid.getEntityName());
+		if (!inheritanceTree.getChildren().isEmpty()) {
+			object = polymorphicObjectFromCache(inheritanceTree, superOid.getIdSnapshot());
+		}
+
+		return object;
+	}
+    
+	private Object polymorphicObjectFromCache(EntityInheritanceTree superNode, Map<String,
?> idSnapshot) {
+
+		for (EntityInheritanceTree child : superNode.getChildren()) {
+			ObjectId id = new ObjectId(child.getEntity().getName(), idSnapshot);
+			Object object = actingContext.getGraphManager().getNode(id);
+			if (object != null) {
+				return object;
+			}
+			
+			object = polymorphicObjectFromCache(child, idSnapshot);
+			if (object != null) {
+				return object;
+			}
+		}
+
+		return null;
+	}
 
     protected boolean interceptRelationshipQuery() {
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/4d76a54e/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextObjectIdQuery_PolymorphicIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextObjectIdQuery_PolymorphicIT.java
b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextObjectIdQuery_PolymorphicIT.java
new file mode 100644
index 0000000..f2c703c
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextObjectIdQuery_PolymorphicIT.java
@@ -0,0 +1,86 @@
+package org.apache.cayenne.access;
+
+import static org.junit.Assert.assertTrue;
+
+import java.sql.SQLException;
+import java.sql.Types;
+
+import org.apache.cayenne.Cayenne;
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.ObjectIdQuery;
+import org.apache.cayenne.test.jdbc.TableHelper;
+import org.apache.cayenne.testdo.inheritance_people.AbstractPerson;
+import org.apache.cayenne.testdo.inheritance_people.Manager;
+import org.apache.cayenne.unit.di.DataChannelInterceptor;
+import org.apache.cayenne.unit.di.UnitTestClosure;
+import org.apache.cayenne.unit.di.server.PeopleProjectCase;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DataContextObjectIdQuery_PolymorphicIT extends PeopleProjectCase {
+
+	@Inject
+	private DataContext context1;
+
+	@Inject
+	private DataContext context2;
+
+	@Inject
+	private DataChannelInterceptor queryInterceptor;
+
+	private TableHelper tPerson;
+
+	@Before
+	public void before() {
+		tPerson = new TableHelper(dbHelper, "PERSON").setColumns("PERSON_ID", "NAME", "PERSON_TYPE")
+				.setColumnTypes(Types.INTEGER, Types.VARCHAR, Types.CHAR);
+	}
+
+	@Test
+	public void testPolymorphicSharedCache() throws SQLException {
+
+		tPerson.insert(1, "P1", "EM");
+
+		final ObjectIdQuery q1 = new ObjectIdQuery(new ObjectId("AbstractPerson", "PERSON_ID",
1), false,
+				ObjectIdQuery.CACHE);
+
+		AbstractPerson ap1 = (AbstractPerson) Cayenne.objectForQuery(context1, q1);
+		assertTrue(ap1 instanceof Manager);
+
+		queryInterceptor.runWithQueriesBlocked(new UnitTestClosure() {
+
+			@Override
+			public void execute() {
+				// use different context to ensure we hit shared cache
+				AbstractPerson ap2 = (AbstractPerson) Cayenne.objectForQuery(context2, q1);
+				assertTrue(ap2 instanceof Manager);
+			}
+		});
+	}
+
+	@Test
+	public void testPolymorphicLocalCache() throws SQLException {
+
+		tPerson.insert(1, "P1", "EM");
+
+		final ObjectIdQuery q1 = new ObjectIdQuery(new ObjectId("AbstractPerson", "PERSON_ID",
1), false,
+				ObjectIdQuery.CACHE);
+
+		AbstractPerson ap1 = (AbstractPerson) Cayenne.objectForQuery(context1, q1);
+		assertTrue(ap1 instanceof Manager);
+
+		queryInterceptor.runWithQueriesBlocked(new UnitTestClosure() {
+
+			@Override
+			public void execute() {
+				// use same context to ensure we hit local cache
+				// note that this does not guarantee test correctness. If local
+				// cache polymorphic ID lookup is broken, shared cache will pick
+				// it up
+				AbstractPerson ap2 = (AbstractPerson) Cayenne.objectForQuery(context1, q1);
+				assertTrue(ap2 instanceof Manager);
+			}
+		});
+	}
+}


Mime
View raw message