You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2020/12/25 13:32:56 UTC

[isis] branch master updated: ISIS-2033: dn-integration: further simplify queries

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 35e416c  ISIS-2033: dn-integration: further simplify queries
35e416c is described below

commit 35e416cd934f914b4619cdba27340d3d96d14013
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Dec 25 14:32:40 2020 +0100

    ISIS-2033: dn-integration: further simplify queries
---
 .../metamodel/facets/entity/JdoEntityFacet.java    |  65 ++++-----
 .../persistence/JdoPersistenceSession5.java        |   4 +-
 .../persistence/_JdoPersistenceSessionBase.java    |   6 +-
 .../{query => command}/FetchResultHandler.java     |   2 +-
 .../persistence/query/PersistenceQuery.java        |  42 ------
 .../persistence/query/PersistenceQueryContext.java |  28 ----
 .../query/PersistenceQueryFindAllInstances.java    |  66 ---------
 ...ersistenceQueryFindUsingApplibQueryDefault.java | 160 ---------------------
 .../query/_PersistenceQueryAbstract.java           |  92 ------------
 .../transaction/TransactionalCommandProcessor.java |   8 +-
 .../transaction/TxManagerInternalFactory.java      |   6 +-
 .../transaction/_TxManagerInternal.java            |  37 ++++-
 12 files changed, 74 insertions(+), 442 deletions(-)

diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java
index 37645cd..b0f4aeb 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java
@@ -19,15 +19,16 @@
 package org.apache.isis.persistence.jdo.integration.metamodel.facets.entity;
 
 import java.lang.reflect.Method;
-import java.util.Collections;
 
 import org.datanucleus.enhancement.Persistable;
+import org.datanucleus.store.rdbms.RDBMSPropertyNames;
 
 import org.apache.isis.applib.query.AllInstancesQuery;
 import org.apache.isis.applib.query.NamedQuery;
 import org.apache.isis.applib.query.Query;
 import org.apache.isis.applib.services.repository.EntityState;
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.assertions._Assert;
 import org.apache.isis.commons.internal.collections._Maps;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -35,9 +36,6 @@ import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.persistence.jdo.datanucleus.entities.DnEntityStateProvider;
 import org.apache.isis.persistence.jdo.integration.metamodel.JdoMetamodelUtil;
-import org.apache.isis.persistence.jdo.integration.persistence.query.PersistenceQueryContext;
-import org.apache.isis.persistence.jdo.integration.persistence.query.PersistenceQueryFindAllInstances;
-import org.apache.isis.persistence.jdo.integration.persistence.query.PersistenceQueryFindUsingApplibQueryDefault;
 
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
@@ -70,8 +68,6 @@ public class JdoEntityFacet extends _JdoEntityFacetAbstract {
         }
         
         val range = query.getRange();
-        final long rangeLower = range.getStart();
-        final long rangeUpper = range.getEnd();
         
         if(query instanceof AllInstancesQuery) {
 
@@ -80,22 +76,22 @@ public class JdoEntityFacet extends _JdoEntityFacetAbstract {
             
             val persistenceManager = getJdoPersistenceSession().getPersistenceManager();
             
-            val typedQuery = persistenceManager.newJDOQLTypedQuery(queryEntityType)
-                    .range(rangeLower, rangeUpper);
+            val typedQuery = persistenceManager.newJDOQLTypedQuery(queryEntityType);
+            typedQuery.extension(RDBMSPropertyNames.PROPERTY_RDBMS_QUERY_MULTIVALUED_FETCH, "none");
             
-            val persistenceQuery = new PersistenceQueryFindAllInstances(
-                    getSpecification(queryEntityType), 
-                    query.getRange());
+            if(!range.isUnconstrained()) {
+                typedQuery.range(range.getStart(), range.getEnd());
+            }
             
-            return getJdoPersistenceSession()
+            val resultList = getJdoPersistenceSession()
                    .getTransactionalProcessor()
-                   .executeWithinTransaction((PersistenceQueryContext) getJdoPersistenceSession(), persistenceQuery);
-
-//TODO more simplification options ...             
-//            return _NullSafe.stream(typedQuery.executeList())
-//                .peek(this::injectServicesInto)
-//                .map(entity->ManagedObject.of(spec, entity))
-//                .collect(Can.toCan());
+                   .executeWithinTransaction(typedQuery::executeList);
+            
+            if(range.hasLimit()) {
+                _Assert.assertTrue(resultList.size()<=range.getLimit());
+            }
+            
+            return resultList;
             
         } else if(query instanceof NamedQuery) {
             
@@ -106,9 +102,12 @@ public class JdoEntityFacet extends _JdoEntityFacetAbstract {
             
             val namedParams = _Maps.<String, Object>newHashMap();
             val namedQuery = persistenceManager.newNamedQuery(queryResultType, applibNamedQuery.getName())
-                    .setNamedParameters(namedParams)
-                    .range(rangeLower, rangeUpper);
+                    .setNamedParameters(namedParams);
+            namedQuery.extension(RDBMSPropertyNames.PROPERTY_RDBMS_QUERY_MULTIVALUED_FETCH, "none");
             
+            if(!range.isUnconstrained()) {
+                namedQuery.range(range.getStart(), range.getEnd());
+            }
             
             // inject services into query params; not sure if required (might be redundant)
             {
@@ -124,25 +123,15 @@ public class JdoEntityFacet extends _JdoEntityFacetAbstract {
                 .getParametersByName()
                 .forEach(namedParams::put);
             
-            val queryName = applibNamedQuery.getName();
-            val parametersByName = applibNamedQuery.getParametersByName();
-            
-            val persistenceQuery = new PersistenceQueryFindUsingApplibQueryDefault(
-                    getSpecification(queryResultType), 
-                    queryName, 
-                    Collections.unmodifiableMap(parametersByName), 
-                    range);
-            
-            return getJdoPersistenceSession()
+            val resultList = getJdoPersistenceSession()
                     .getTransactionalProcessor()
-                    .executeWithinTransaction((PersistenceQueryContext) getJdoPersistenceSession(), persistenceQuery);
-
-//TODO more simplification options ...            
-//            return _NullSafe.stream(namedQuery.executeList())
-//                    .peek(this::injectServicesInto)
-//                    .map(entity->ManagedObject.of(spec, entity))
-//                    .collect(Can.toCan());
+                    .executeWithinTransaction(namedQuery::executeList);
+            
+            if(range.hasLimit()) {
+                _Assert.assertTrue(resultList.size()<=range.getLimit());
+            }
             
+            return resultList;
         }
         
         throw _Exceptions.unsupportedOperation("query type %s (%s) not supported by this persistence implementation",
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java
index e9933aa..6a7134b 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java
@@ -44,7 +44,7 @@ import org.apache.isis.persistence.jdo.integration.lifecycles.JdoStoreLifecycleL
 import org.apache.isis.persistence.jdo.integration.lifecycles.LoadLifecycleListenerForIsis;
 import org.apache.isis.persistence.jdo.integration.persistence.command.CreateObjectCommand;
 import org.apache.isis.persistence.jdo.integration.persistence.command.DeleteObjectCommand;
-import org.apache.isis.persistence.jdo.integration.persistence.query.PersistenceQueryContext;
+import org.apache.isis.persistence.jdo.integration.persistence.command.FetchResultHandler;
 import org.apache.isis.persistence.jdo.integration.transaction.TransactionalCommandProcessor;
 
 import lombok.NonNull;
@@ -57,7 +57,7 @@ import lombok.extern.log4j.Log4j2;
 @Vetoed @Log4j2
 public class JdoPersistenceSession5 extends _JdoPersistenceSessionBase
 implements
-    PersistenceQueryContext,
+    FetchResultHandler,
     IsisLifecycleListener.EntityChangeEmitter {
 
     private Runnable unregisterLifecycleListeners;
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/_JdoPersistenceSessionBase.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/_JdoPersistenceSessionBase.java
index 525095a..e9f8657 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/_JdoPersistenceSessionBase.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/_JdoPersistenceSessionBase.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
 import org.apache.isis.core.transaction.changetracking.EntityChangeTracker;
 import org.apache.isis.persistence.jdo.applib.fixturestate.FixturesInstalledStateHolder;
+import org.apache.isis.persistence.jdo.integration.persistence.command.FetchResultHandler;
 import org.apache.isis.persistence.jdo.integration.transaction.TransactionalCommandProcessor;
 import org.apache.isis.persistence.jdo.integration.transaction.TxManagerInternalFactory;
 
@@ -76,7 +77,10 @@ implements JdoPersistenceSession {
         this.fixturesInstalledStateHolder = fixturesInstalledStateHolder;
 
         // sub-components
-        this.txCommandProcessor = TxManagerInternalFactory.newCommandQueue(metaModelContext, this); 
+        this.txCommandProcessor = TxManagerInternalFactory.newCommandQueue(
+                metaModelContext, 
+                this,
+                (FetchResultHandler)this); 
 
         this.state = State.NOT_INITIALIZED;
     }
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/FetchResultHandler.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/FetchResultHandler.java
similarity index 99%
rename from persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/FetchResultHandler.java
rename to persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/FetchResultHandler.java
index 0c0c931..b490301 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/FetchResultHandler.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/FetchResultHandler.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.persistence.jdo.integration.persistence.query;
+package org.apache.isis.persistence.jdo.integration.persistence.command;
 
 import org.datanucleus.enhancement.Persistable;
 
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQuery.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQuery.java
deleted file mode 100644
index e20f267..0000000
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQuery.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  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.isis.persistence.jdo.integration.persistence.query;
-
-import org.apache.isis.applib.query.Query;
-import org.apache.isis.applib.query.QueryRange;
-import org.apache.isis.commons.collections.Can;
-import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-
-/**
- * Defines a criteria for including instances in set, corresponds to
- * {@link Query} in the applib.
- */
-public interface PersistenceQuery {
-
-    /**
-     * The type of instances in the resulting set.
-     */
-    ObjectSpecification getSpecification();
-
-    QueryRange getQueryRange() ;
-
-    Can<ManagedObject> execute(PersistenceQueryContext queryContext);
-}
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQueryContext.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQueryContext.java
deleted file mode 100644
index dd3b73b..0000000
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQueryContext.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  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.isis.persistence.jdo.integration.persistence.query;
-
-import org.apache.isis.persistence.jdo.provider.persistence.HasPersistenceManager;
-
-public interface PersistenceQueryContext 
-extends
-    FetchResultHandler,
-    HasPersistenceManager {
-
-}
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQueryFindAllInstances.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQueryFindAllInstances.java
deleted file mode 100644
index da9d369..0000000
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQueryFindAllInstances.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *  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.isis.persistence.jdo.integration.persistence.query;
-
-import org.apache.isis.applib.query.AllInstancesQuery;
-import org.apache.isis.applib.query.QueryRange;
-import org.apache.isis.commons.collections.Can;
-import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-
-import lombok.val;
-import lombok.extern.log4j.Log4j2;
-
-/**
- * Corresponds to {@link AllInstancesQuery}
- */
-@Log4j2
-public class PersistenceQueryFindAllInstances extends _PersistenceQueryAbstract  {
-
-    public PersistenceQueryFindAllInstances(
-            final ObjectSpecification specification,
-            final QueryRange range) {
-        super(specification, range);
-    }
-
-    @Override
-    public Can<ManagedObject> execute(PersistenceQueryContext queryContext) {
-
-        val persistenceQuery = this;
-        
-        val spec = persistenceQuery.getSpecification();
-        val cls = spec.getCorrespondingClass();
-        
-        val serviceRegistry = spec.getMetaModelContext().getServiceRegistry();
-        val isisJdoSupport = isisJdoSupport(serviceRegistry);
-
-        val typesafeQuery = isisJdoSupport.newTypesafeQuery(cls);
-        isisJdoSupport.disableMultivaluedFetch(typesafeQuery); // fetch optimization
-
-        if (log.isDebugEnabled()) {
-            log.debug("allInstances(): class={}", spec.getFullIdentifier());
-        }
-
-        val pojos = isisJdoSupport.executeQuery(cls);
-        return loadAdapters(queryContext, pojos);
-
-    }
-    
-}
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQueryFindUsingApplibQueryDefault.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQueryFindUsingApplibQueryDefault.java
deleted file mode 100644
index a1bdfc0..0000000
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/PersistenceQueryFindUsingApplibQueryDefault.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- *  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.isis.persistence.jdo.integration.persistence.query;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.isis.applib.query.Query;
-import org.apache.isis.applib.query.QueryRange;
-import org.apache.isis.commons.collections.Can;
-import org.apache.isis.commons.internal.assertions._Assert;
-import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-import org.apache.isis.persistence.jdo.integration.metamodel.JdoPropertyUtils;
-
-import lombok.Getter;
-import lombok.val;
-import lombok.extern.log4j.Log4j2;
-
-/**
- * Corresponds to an object-store specific implementation of {@link Query}.
- */
-@Log4j2
-public class PersistenceQueryFindUsingApplibQueryDefault extends _PersistenceQueryAbstract {
-
-    @Getter private final String queryName;
-    @Getter private final Map<String, Object> queryParametersByName;
-
-    public PersistenceQueryFindUsingApplibQueryDefault(
-            final ObjectSpecification specification,
-            final String queryName,
-            final Map<String, Object> queryParametersByName,
-            final QueryRange range) {
-        super(specification, range);
-        this.queryName = queryName;
-        this.queryParametersByName = queryParametersByName;
-    }
-
-    @Override
-    public Can<ManagedObject> execute(PersistenceQueryContext queryContext) {
-
-        val persistenceQuery = this;
-        
-        val queryName = persistenceQuery.getQueryName();
-        val objectSpec = persistenceQuery.getSpecification();
-
-        val resultList = (objectSpec.getFullIdentifier() + "#pk").equals(queryName)
-                ? getResultsPk(queryContext, persistenceQuery)
-                : getResults(queryContext, persistenceQuery);
-
-        return loadAdapters(queryContext, resultList);
-    }
-
-    // -- HELPER
-
-    // special case handling
-    private List<?> getResultsPk(
-            final PersistenceQueryContext queryContext,
-            final PersistenceQueryFindUsingApplibQueryDefault persistenceQuery) {
-
-        val queryName = persistenceQuery.getQueryName();
-        val queryParametersByName = persistenceQuery.getQueryParametersByName();
-        val spec = persistenceQuery.getSpecification();
-        
-        val isisJdoSupport = isisJdoSupport(spec.getMetaModelContext().getServiceRegistry());
-
-        val cls = spec.getCorrespondingClass();
-        if(!JdoPropertyUtils.hasPrimaryKeyProperty(spec)) {
-            throw new UnsupportedOperationException("cannot search by primary key for DataStore-assigned entities");
-        }
-        final OneToOneAssociation pkOtoa = JdoPropertyUtils.getPrimaryKeyPropertyFor(spec);
-        final String pkOtoaId = pkOtoa.getId();
-        final String filter = pkOtoaId + "==" + queryParametersByName.get(pkOtoaId);
-
-        /* XXX[ISIS-2020] as of Oct. 2018: likely not working on FederatedDataStore
-         * see PersistenceQueryFindAllInstancesProcessor for workaround using type-safe query instead
-         */
-        //final Query<?> 
-        val jdoQuery = queryContext.newJdoQuery(cls, filter);
-        isisJdoSupport.disableMultivaluedFetch(jdoQuery); // fetch optimization
-
-        if (log.isDebugEnabled()) {
-            log.debug("{} # {} ( {} )", cls.getName(), queryName, filter);
-        }
-
-        try {
-            final List<?> results = (List<?>) jdoQuery.execute();
-            return _Lists.newArrayList(results);
-        } finally {
-            jdoQuery.closeAll();
-        }
-    }
-
-    private List<?> getResults(
-            final PersistenceQueryContext queryContext,
-            final PersistenceQueryFindUsingApplibQueryDefault persistenceQuery) {
-
-        val queryName = persistenceQuery.getQueryName();
-        val queryParametersByName = persistenceQuery.getQueryParametersByName();
-        val spec = persistenceQuery.getSpecification();
-        val cls = spec.getCorrespondingClass();
-        
-        val serviceRegistry = spec.getMetaModelContext().getServiceRegistry();
-        val isisJdoSupport = isisJdoSupport(serviceRegistry);
-
-        /* XXX[ISIS-2020] as of Oct. 2018: likely not working on FederatedDataStore
-         * see PersistenceQueryFindAllInstancesProcessor for workaround using type-safe query instead 
-         */
-        //final Query<?> 
-        val jdoQuery = queryContext.newJdoNamedQuery(cls, queryName); 
-        isisJdoSupport.disableMultivaluedFetch(jdoQuery);
-
-        val range = persistenceQuery.getQueryRange();
-        
-        if(!range.isUnconstrained()) {
-            jdoQuery.setRange(range.getStart(), range.getEnd());
-        }
-
-        if (log.isDebugEnabled()) {
-            log.debug("{} # {} ( {} )", cls.getName(), queryName, queryParametersByName);
-        }
-        
-        try {
-            val resultList = (List<?>) jdoQuery.executeWithMap(queryParametersByName);
-            if(resultList == null
-                    || resultList.isEmpty()) {
-                return Collections.emptyList();
-            }
-            
-            if(range.hasLimit()) {
-                _Assert.assertTrue(resultList.size()<=range.getLimit());
-            }
-            
-            // puzzler: needs a defensive copy, not sure why
-            return _Lists.newArrayList(resultList);
-        } finally {
-            jdoQuery.closeAll();
-        }
-    }
-}
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/_PersistenceQueryAbstract.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/_PersistenceQueryAbstract.java
deleted file mode 100644
index 66e5ce0..0000000
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/query/_PersistenceQueryAbstract.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *  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.isis.persistence.jdo.integration.persistence.query;
-
-import java.util.List;
-
-import javax.jdo.listener.InstanceLifecycleEvent;
-
-import org.datanucleus.enhancement.Persistable;
-
-import org.apache.isis.applib.query.QueryRange;
-import org.apache.isis.applib.services.registry.ServiceRegistry;
-import org.apache.isis.commons.collections.Can;
-import org.apache.isis.commons.internal.assertions._Assert;
-import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.core.metamodel.commons.ToString;
-import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.persistence.jdo.applib.services.IsisJdoSupport_v3_2;
-import org.apache.isis.persistence.jdo.integration.lifecycles.IsisLifecycleListener;
-
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-import lombok.val;
-
-@RequiredArgsConstructor 
-@Getter @EqualsAndHashCode
-abstract class _PersistenceQueryAbstract implements PersistenceQuery {
-
-    // -- constructor, fields
-
-    protected final @NonNull ObjectSpecification specification;
-    protected final @NonNull QueryRange queryRange;
-    
-    @Override
-    public String toString() {
-        final ToString str = ToString.createAnonymous(this);
-        str.append("spec", getSpecification().getShortIdentifier());
-        return str.toString();
-    }
-
-    // -- HELPER
-    
-    /**
-     * Traversing the provided list causes (or should cause) the
-     * {@link IsisLifecycleListener#postLoad(InstanceLifecycleEvent) {
-     * to be called.
-     */
-    protected Can<ManagedObject> loadAdapters(final PersistenceQueryContext queryContext, final List<?> pojos) {
-        val adapters = _Lists.<ManagedObject>newArrayList();
-        for (val pojo : pojos) {
-            // ought not to be necessary, however for some queries it seems that the
-            // lifecycle listener is not called
-            ManagedObject adapter;
-            if(pojo instanceof Persistable) {
-                // an entity
-                adapter = queryContext.initializeEntityAfterFetched((Persistable) pojo);
-                _Assert.assertNotNull(adapter);
-            } else {
-                // a value type
-                adapter = queryContext.initializeValueAfterFetched(pojo);
-                _Assert.assertNotNull(adapter);
-            }
-            adapters.add(adapter);
-        }
-        return Can.ofCollection(adapters);
-    }
-
-    protected static IsisJdoSupport_v3_2 isisJdoSupport(ServiceRegistry serviceRegistry) { 
-        return serviceRegistry.lookupServiceElseFail(IsisJdoSupport_v3_2.class);
-    }
-
-}
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TransactionalCommandProcessor.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TransactionalCommandProcessor.java
index 393b62c..1dad220 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TransactionalCommandProcessor.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TransactionalCommandProcessor.java
@@ -18,17 +18,19 @@
  */
 package org.apache.isis.persistence.jdo.integration.transaction;
 
+import java.util.List;
+import java.util.function.Supplier;
+
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.persistence.jdo.integration.persistence.command.PersistenceCommand;
-import org.apache.isis.persistence.jdo.integration.persistence.query.PersistenceQuery;
-import org.apache.isis.persistence.jdo.integration.persistence.query.PersistenceQueryContext;
 
 public interface TransactionalCommandProcessor {
 
     void executeWithinTransaction(PersistenceCommand persistenceCommand);
 
-    Can<ManagedObject> executeWithinTransaction(PersistenceQueryContext queryContext, PersistenceQuery persistenceQuery);
+    Can<ManagedObject> executeWithinTransaction(Supplier<List<?>> fetcher);
+    
     
     //void createObject(ManagedObject adapter);
     //void deleteObject(ManagedObject adapter);
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TxManagerInternalFactory.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TxManagerInternalFactory.java
index 4b11272..6936014 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TxManagerInternalFactory.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TxManagerInternalFactory.java
@@ -20,6 +20,7 @@ package org.apache.isis.persistence.jdo.integration.transaction;
 
 import org.apache.isis.core.interaction.session.InteractionTracker;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
+import org.apache.isis.persistence.jdo.integration.persistence.command.FetchResultHandler;
 import org.apache.isis.persistence.jdo.provider.persistence.HasPersistenceManager;
 
 import lombok.val;
@@ -28,9 +29,10 @@ public class TxManagerInternalFactory {
 
     public static TransactionalCommandProcessor newCommandQueue(
             MetaModelContext mmc,
-            HasPersistenceManager pmProvider) {
+            HasPersistenceManager pmProvider,
+            FetchResultHandler fetchResultHandler) {
         
-        val txMan = new _TxManagerInternal(mmc, pmProvider);
+        val txMan = new _TxManagerInternal(mmc, pmProvider, fetchResultHandler);
         
         val isisInteractionTracker = mmc.getServiceRegistry()
                 .lookupServiceElseFail(InteractionTracker.class);
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxManagerInternal.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxManagerInternal.java
index 8404ed0..4b81a7c 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxManagerInternal.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxManagerInternal.java
@@ -19,23 +19,26 @@
 
 package org.apache.isis.persistence.jdo.integration.transaction;
 
+import java.util.List;
 import java.util.function.Supplier;
 
 import javax.enterprise.inject.Vetoed;
 
+import org.datanucleus.enhancement.Persistable;
+
 import org.apache.isis.applib.services.iactn.Interaction;
 import org.apache.isis.applib.services.iactn.InteractionContext;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.exceptions.IsisException;
+import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.transaction.integration.IsisTransactionAspectSupport;
 import org.apache.isis.core.transaction.integration.IsisTransactionManagerException;
 import org.apache.isis.core.transaction.integration.IsisTransactionObject;
+import org.apache.isis.persistence.jdo.integration.persistence.command.FetchResultHandler;
 import org.apache.isis.persistence.jdo.integration.persistence.command.PersistenceCommand;
-import org.apache.isis.persistence.jdo.integration.persistence.query.PersistenceQuery;
-import org.apache.isis.persistence.jdo.integration.persistence.query.PersistenceQueryContext;
 import org.apache.isis.persistence.jdo.provider.persistence.HasPersistenceManager;
 
 import lombok.val;
@@ -51,14 +54,17 @@ implements
     private final MetaModelContext mmc;
     private final Supplier<InteractionContext> interactionContextProvider;
     private final _TxHelper txHelper;
+    private final FetchResultHandler fetchResultHandler;
 
     _TxManagerInternal(
             MetaModelContext mmc, 
-            HasPersistenceManager pmProvider) {
+            HasPersistenceManager pmProvider,
+            FetchResultHandler fetchResultHandler) {
 
         this.mmc = mmc;
         this.interactionContextProvider = ()->mmc.getServiceRegistry().lookupServiceElseFail(InteractionContext.class);
         this.txHelper = _TxHelper.create(pmProvider);
+        this.fetchResultHandler = fetchResultHandler;
     }
 
     public _Tx beginTransaction() {
@@ -335,17 +341,32 @@ implements
     }
     
     @Override
-    public Can<ManagedObject> executeWithinTransaction(
-            PersistenceQueryContext queryContext, 
-            PersistenceQuery persistenceQuery) {
+    public Can<ManagedObject> executeWithinTransaction(Supplier<List<?>> fetcher) {
         final Can<ManagedObject> instances = mmc.getTransactionService().executeWithinTransaction(
-                        ()->persistenceQuery.execute(queryContext) )
+                ()->_NullSafe.stream(fetcher.get())
+                    .map(this::adopt)
+                    .collect(Can.toCan()))
                 .orElseFail();
         return instances;
     }
 
     // -- HELPER
 
+    private ManagedObject adopt(final Object fetchedObject) {
+        // handles lifecycle callbacks and injects services
+        
+        // ought not to be necessary, however for some queries it seems that the
+        // lifecycle listener is not called
+        if(fetchedObject instanceof Persistable) {
+            // an entity
+            return fetchResultHandler.initializeEntityAfterFetched((Persistable) fetchedObject);
+            
+        } else {
+            // a value type
+            return fetchResultHandler.initializeValueAfterFetched(fetchedObject);
+        }
+    }
+    
     private _Tx getCurrentTransaction() {
         return IsisTransactionAspectSupport.currentTransactionObject()
                 .map(IsisTransactionObject::getCurrentTransaction)
@@ -354,4 +375,6 @@ implements
     }
 
 
+
+
 }