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

danhaywood pushed a commit to branch CAUSEWAY-3675
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit b3d723badca36c934177ae7e5931bc6a4260ff0b
Author: danhaywood <[email protected]>
AuthorDate: Tue Jan 16 16:09:07 2024 +0000

    CAUSEWAY-3675: adds suppress-auto-flush functionality
---
 .../ROOT/pages/2024/2.0.0-RC5/mignotes.adoc        |  23 ++++-
 .../core/config/CausewayConfiguration.java         |  63 +++++++++++--
 .../CausewayModuleCoreRuntimeServices.java         |   4 -
 .../commons/CausewayModulePersistenceCommons.java  |   7 ++
 .../changetracking/EntityChangeTrackerDefault.java | 100 +++++++++++++--------
 .../PreAndPostValueEvaluatorServiceDefault.java    |   4 +-
 .../repository/RepositoryServiceDefault.java       |  26 ++++--
 7 files changed, 173 insertions(+), 54 deletions(-)

diff --git 
a/antora/components/relnotes/modules/ROOT/pages/2024/2.0.0-RC5/mignotes.adoc 
b/antora/components/relnotes/modules/ROOT/pages/2024/2.0.0-RC5/mignotes.adoc
index ab856cb7e5..ad2e59b983 100644
--- a/antora/components/relnotes/modules/ROOT/pages/2024/2.0.0-RC5/mignotes.adoc
+++ b/antora/components/relnotes/modules/ROOT/pages/2024/2.0.0-RC5/mignotes.adoc
@@ -5,9 +5,7 @@
 
 This page will be added to as development progresses.
 
-== AuditTrailEntryRepository and others have simplified the API.
-
-
+== AuditTrailEntryRepository and others have simplified the API (CAUSEWAY-3390)
 
 In this release the `AuditTrailEntryRepository` and similar is no longer 
parameterized by the entity type, and is also an interface.
 
@@ -35,3 +33,22 @@ This applies to:
 
 For more details, see 
link:https://issues.apache.org/jira/browse/CAUSEWAY-3390[CAUSEWAY-3390].
 
+
+== Auto-flush management (CAUSEWAY-3675)
+
+By default any queries executed by 
xref:refguide:applib:index/services/repository/RepositoryService.adoc[] are 
preceded by a flush first.
+The rationale behind this is to make sure that everything that might have 
changed is in the database.
+
+However, with JDO at least, this behaviour can cause a 
`ConcurrentModificationException` when coupled with the  
xref:refguide:persistence:index/commons/integration/changetracking/EntityChangeTrackerDefault.adoc[]
 internal service, used by auditing.
+This grabs the value of properties, including derived properties that are 
evaluated using a query.
+
+So now, 
xref:refguide:persistence:index/commons/integration/changetracking/EntityChangeTrackerDefault.adoc[]
 suppresses the autoflush.
+
+Changes:
+
+* To revert to the original behaviour, use the new 
`causeway.commons.persistence.entity-change-tracker.suppress-auto-flush` 
property.
+
+* The `causeway.core.runtime-services.repository=service.disable-auto-flush` 
configuration property has been renamed to 
`causeway.commons.persistence.repository-service.disable-auto-flush`.
+
+For more details, see 
link:https://issues.apache.org/jira/browse/CAUSEWAY-3675[CAUSEWAY-3675].
+
diff --git 
a/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
 
b/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
index c6bd442731..7f05a9e4e1 100644
--- 
a/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
+++ 
b/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
@@ -57,8 +57,11 @@ import javax.validation.constraints.Min;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 
+import org.apache.causeway.applib.query.Query;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.context.properties.ConfigurationProperties;
+import 
org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
 import org.springframework.boot.info.BuildProperties;
 import org.springframework.core.env.ConfigurableEnvironment;
 import org.springframework.core.env.EnumerablePropertySource;
@@ -1925,19 +1928,21 @@ public class CausewayConfiguration {
             private final RepositoryService repositoryService = new 
RepositoryService();
             @Data
             public static class RepositoryService {
+                private boolean disableAutoFlush = false;
+
                 /**
                  * Normally any queries are automatically preceded by flushing 
pending executions.
                  *
                  * <p>
                  * This key allows this behaviour to be disabled.
-                 *
-                 * <p>
-                 *     NOTE: this key is redundant for JPA/EclipseLink, which 
supports its own auto-flush using
-                 *     <a 
href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BABDHEEB";>eclipselink.persistence-context.flush-mode</a>
                  * </p>
+                 *
+                 * @deprecated - use instead 
<code>causeway.persistence.commons.repository-service.disable-auto-flush</code>
                  */
-                private boolean disableAutoFlush = false;
-
+                @DeprecatedConfigurationProperty(replacement = 
"causeway.persistence.commons.repository-service.disable-auto-flush")
+                public boolean isDisableAutoFlush() {
+                    return disableAutoFlush;
+                }
             }
 
             private final ExceptionRecognizer exceptionRecognizer = new 
ExceptionRecognizer();
@@ -2015,6 +2020,52 @@ public class CausewayConfiguration {
     @Data
     public static class Persistence {
 
+        private final Commons commons = new Commons();
+        @Data
+        public static class Commons {
+
+            private final RepositoryService repositoryService = new 
RepositoryService();
+            @Data
+            public static class RepositoryService {
+
+                /**
+                 * Normally any queries are automatically preceded by flushing 
pending executions.
+                 *
+                 * <p>
+                 * This key allows this behaviour to be disabled.
+                 *
+                 * <p>
+                 *     NOTE: this key is redundant for JPA/EclipseLink, which 
supports its own auto-flush using
+                 *     <a 
href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BABDHEEB";>eclipselink.persistence-context.flush-mode</a>
+                 * </p>
+                 */
+                private boolean disableAutoFlush = false;
+            }
+
+            private final EntityChangeTracker entityChangeTracker = new 
EntityChangeTracker();
+            @Data
+            public static class EntityChangeTracker {
+                /**
+                 * Normally any query submitted to {@link 
org.apache.causeway.applib.services.repository.RepositoryService#allMatches(Query)}
 will trigger a
+                 * flush first, unless auto-flush has been {@link 
Core.RuntimeServices.RepositoryService#isDisableAutoFlush() disabled}.
+                 *
+                 * <p>
+                 *     However, this auto-flush behaviour can be troublesome 
if the query occurs as a side-effect of the evaluation of a derived property,
+                 *     whose value in turn is enlisted by an implementation of 
a subscriber (in particular {@link EntityPropertyChangeSubscriber}) which
+                 *     captures the value of all properties (both persisted 
and derived).  However, this behaviour can (at least under JDO), result in a 
{@link java.util.ConcurrentModificationException}.
+                 * </p>
+                 *
+                 * <p>
+                 *     By default, {@link EntityChangeTracker} will therefore 
temporarily suppress any auto-flushing while this is ongoing.  The purpose
+                 *     of this configuration property is to never suppress, ie 
always autoflush.
+                 * </p>
+                 */
+                private boolean suppressAutoFlush = true;
+            }
+
+        }
+
+
         private final Schema schema = new Schema();
         @Data
         public static class Schema {
diff --git 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/CausewayModuleCoreRuntimeServices.java
 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/CausewayModuleCoreRuntimeServices.java
index 5810ce7d02..b90d5898bc 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/CausewayModuleCoreRuntimeServices.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/CausewayModuleCoreRuntimeServices.java
@@ -57,7 +57,6 @@ import 
org.apache.causeway.core.runtimeservices.publish.LifecycleCallbackNotifie
 import 
org.apache.causeway.core.runtimeservices.publish.ObjectLifecyclePublisherDefault;
 import 
org.apache.causeway.core.runtimeservices.recognizer.ExceptionRecognizerServiceDefault;
 import 
org.apache.causeway.core.runtimeservices.recognizer.dae.ExceptionRecognizerForDataAccessException;
-import 
org.apache.causeway.core.runtimeservices.repository.RepositoryServiceDefault;
 import org.apache.causeway.core.runtimeservices.routing.RoutingServiceDefault;
 import org.apache.causeway.core.runtimeservices.scratchpad.ScratchpadDefault;
 import 
org.apache.causeway.core.runtimeservices.serializing.SerializingAdapterDefault;
@@ -126,9 +125,6 @@ import 
org.apache.causeway.core.runtimeservices.xmlsnapshot.XmlSnapshotServiceDe
         // @Controller
         RoutingServiceDefault.class,
 
-        // @Repository's
-        RepositoryServiceDefault.class,
-
         // @DomainService's
         TranslationServicePoMenu.class,
 
diff --git 
a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/CausewayModulePersistenceCommons.java
 
b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/CausewayModulePersistenceCommons.java
index ac62cade36..c8da4c1e17 100644
--- 
a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/CausewayModulePersistenceCommons.java
+++ 
b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/CausewayModulePersistenceCommons.java
@@ -18,6 +18,8 @@
  */
 package org.apache.causeway.persistence.commons;
 
+import 
org.apache.causeway.persistence.commons.integration.repository.RepositoryServiceDefault;
+
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 
@@ -33,7 +35,12 @@ import 
org.apache.causeway.persistence.commons.integration.changetracking.PreAnd
         // @Service's
         EntityChangeTrackerDefault.class,
         PreAndPostValueEvaluatorServiceDefault.class,
+
+        // @Repository's
+        RepositoryServiceDefault.class,
+
 })
 public class CausewayModulePersistenceCommons {
 
+    public static final String NAMESPACE = "causeway.persistence.commons";
 }
diff --git 
a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/integration/changetracking/EntityChangeTrackerDefault.java
 
b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/integration/changetracking/EntityChangeTrackerDefault.java
index dbf8911f1b..62c70f0941 100644
--- 
a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/integration/changetracking/EntityChangeTrackerDefault.java
+++ 
b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/integration/changetracking/EntityChangeTrackerDefault.java
@@ -27,10 +27,16 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.LongAdder;
 import java.util.function.Function;
 
+import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Provider;
 
+import org.apache.causeway.core.config.CausewayConfiguration;
+import 
org.apache.causeway.persistence.commons.CausewayModulePersistenceCommons;
+
+import 
org.apache.causeway.persistence.commons.integration.repository.RepositoryServiceDefault;
+
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.core.Ordered;
 import org.springframework.lang.Nullable;
@@ -90,7 +96,7 @@ import lombok.extern.log4j.Log4j2;
  */
 @Service
 @TransactionScope
-@Named("causeway.persistence.commons.EntityChangeTrackerDefault")
+@Named(CausewayModulePersistenceCommons.NAMESPACE + 
".EntityChangeTrackerDefault")
 @Qualifier("default")
 @RequiredArgsConstructor(onConstructor_ = {@Inject})
 @Log4j2
@@ -113,6 +119,7 @@ implements
     private final EntityChangesPublisher entityChangesPublisher;
     private final Provider<InteractionProvider> interactionProviderProvider;
     private final PreAndPostValueEvaluatorService 
preAndPostValueEvaluatorService;
+    private final CausewayConfiguration causewayConfiguration;
 
     /**
      * Contains a record for every objectId/propertyId that was changed.
@@ -135,6 +142,14 @@ implements
     private final AtomicBoolean persistentChangesEncountered = new 
AtomicBoolean();
 
 
+    private boolean suppressAutoFlush;
+
+    @PostConstruct
+    public void init() {
+        this.suppressAutoFlush = 
causewayConfiguration.getPersistence().getCommons().getEntityChangeTracker().isSuppressAutoFlush();
+    }
+
+
     @Override
     public void destroy() throws Exception {
         enlistedPropertyChangeRecordsById.clear();
@@ -146,6 +161,15 @@ implements
         persistentChangesEncountered.set(false);
     }
 
+    private void suppressAutoFlushIfRequired(Runnable runnable) {
+        if (suppressAutoFlush) {
+            RepositoryServiceDefault.suppressAutoFlush(runnable);
+        } else {
+            runnable.run();
+        }
+    }
+
+
     Set<PropertyChangeRecord> snapshotPropertyChangeRecords() {
         // this code path has side-effects, it locks the result for this 
transaction,
         // such that cannot enlist on top of it
@@ -309,12 +333,14 @@ implements
             return;
         }
 
-        log.debug("enlist entity's property changes for publishing {}", 
entity);
-        enlistForChangeKindPublishing(entity, EntityChangeKind.CREATE);
+        suppressAutoFlushIfRequired(() -> {
+            log.debug("enlist entity's property changes for publishing {}", 
entity);
+            enlistForChangeKindPublishing(entity, EntityChangeKind.CREATE);
 
-        MmEntityUtils.streamPropertyChangeRecordIdsForChangePublishing(entity)
-                .filter(pcrId -> ! 
enlistedPropertyChangeRecordsById.containsKey(pcrId)) // only if not previously 
seen
-                .forEach(pcrId -> enlistedPropertyChangeRecordsById.put(pcrId, 
PropertyChangeRecord.ofNew(pcrId)));
+            
MmEntityUtils.streamPropertyChangeRecordIdsForChangePublishing(entity)
+                    .filter(pcrId -> ! 
enlistedPropertyChangeRecordsById.containsKey(pcrId)) // only if not previously 
seen
+                    .forEach(pcrId -> 
enlistedPropertyChangeRecordsById.put(pcrId, 
PropertyChangeRecord.ofNew(pcrId)));
+        });
     }
 
     @Override
@@ -330,28 +356,30 @@ implements
 
         log.debug("enlist entity's property changes for publishing {}", 
entity);
 
-        // we call this come what may;
-        // additional properties may now have been changed, and the changeKind 
for publishing might also be modified
-        enlistForChangeKindPublishing(entity, EntityChangeKind.UPDATE);
-
-        final Can<PropertyChangeRecord> ormPropertyChangeRecords = 
propertyChangeRecordSupplier!=null
-                ? propertyChangeRecordSupplier.apply(entity)
-                : null;
-
-        if(ormPropertyChangeRecords != null) {
-            // provided by ORM
-            ormPropertyChangeRecords
-                    .stream()
-                    .filter(pcr -> ! 
enlistedPropertyChangeRecordsById.containsKey(pcr.getId())) // only if not 
previously seen
-                    .forEach(pcr -> 
enlistedPropertyChangeRecordsById.put(pcr.getId(), pcr));
-        } else {
-            // home-grown approach
-            
MmEntityUtils.streamPropertyChangeRecordIdsForChangePublishing(entity)
-                    .filter(pcrId -> ! 
enlistedPropertyChangeRecordsById.containsKey(pcrId)) // only if not previously 
seen
-                    .map(pcrId -> enlistedPropertyChangeRecordsById.put(pcrId, 
PropertyChangeRecord.ofCurrent(pcrId)))
-                    .filter(Objects::nonNull)   // shouldn't happen, just 
keeping compiler happy
-                    .forEach(PropertyChangeRecord::withPreValueSetToCurrent);
-        }
+        suppressAutoFlushIfRequired(() -> {
+            // we call this come what may;
+            // additional properties may now have been changed, and the 
changeKind for publishing might also be modified
+            enlistForChangeKindPublishing(entity, EntityChangeKind.UPDATE);
+
+            final Can<PropertyChangeRecord> ormPropertyChangeRecords = 
propertyChangeRecordSupplier !=null
+                    ? propertyChangeRecordSupplier.apply(entity)
+                    : null;
+
+            if(ormPropertyChangeRecords != null) {
+                // provided by ORM
+                ormPropertyChangeRecords
+                        .stream()
+                        .filter(pcr -> ! 
enlistedPropertyChangeRecordsById.containsKey(pcr.getId())) // only if not 
previously seen
+                        .forEach(pcr -> 
enlistedPropertyChangeRecordsById.put(pcr.getId(), pcr));
+            } else {
+                // home-grown approach
+                
MmEntityUtils.streamPropertyChangeRecordIdsForChangePublishing(entity)
+                        .filter(pcrId -> ! 
enlistedPropertyChangeRecordsById.containsKey(pcrId)) // only if not previously 
seen
+                        .map(pcrId -> 
enlistedPropertyChangeRecordsById.put(pcrId, 
PropertyChangeRecord.ofCurrent(pcrId)))
+                        .filter(Objects::nonNull)   // shouldn't happen, just 
keeping compiler happy
+                        
.forEach(PropertyChangeRecord::withPreValueSetToCurrent);
+            }
+        });
     }
 
     @Override
@@ -363,14 +391,16 @@ implements
             return;
         }
 
-        final boolean enlisted = enlistForChangeKindPublishing(entity, 
EntityChangeKind.DELETE);
-        if(enlisted) {
-            log.debug("enlist entity's property changes for publishing {}", 
entity);
+        suppressAutoFlushIfRequired(() -> {
+            final boolean enlisted = enlistForChangeKindPublishing(entity, 
EntityChangeKind.DELETE);
+            if(enlisted) {
+                log.debug("enlist entity's property changes for publishing 
{}", entity);
 
-            
MmEntityUtils.streamPropertyChangeRecordIdsForChangePublishing(entity)
-                    .forEach(pcrId -> enlistedPropertyChangeRecordsById
-                            .computeIfAbsent(pcrId, id -> 
PropertyChangeRecord.ofDeleting(id)));
-        }
+                
MmEntityUtils.streamPropertyChangeRecordIdsForChangePublishing(entity)
+                        .forEach(pcrId -> enlistedPropertyChangeRecordsById
+                                .computeIfAbsent(pcrId, id -> 
PropertyChangeRecord.ofDeleting(id)));
+            }
+        });
     }
 
     /**
diff --git 
a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/integration/changetracking/PreAndPostValueEvaluatorServiceDefault.java
 
b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/integration/changetracking/PreAndPostValueEvaluatorServiceDefault.java
index 211c828368..cac2e76d5b 100644
--- 
a/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/integration/changetracking/PreAndPostValueEvaluatorServiceDefault.java
+++ 
b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/integration/changetracking/PreAndPostValueEvaluatorServiceDefault.java
@@ -23,6 +23,8 @@ import javax.annotation.Priority;
 import javax.inject.Inject;
 import javax.inject.Named;
 
+import 
org.apache.causeway.persistence.commons.CausewayModulePersistenceCommons;
+
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 
@@ -34,7 +36,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @Service
-@Named("causeway.persistence.commons.PreAndPostValueEvaluatorServiceDefault")
+@Named(CausewayModulePersistenceCommons.NAMESPACE + 
".PreAndPostValueEvaluatorServiceDefault")
 @Priority(PriorityPrecedence.LATE)
 @Qualifier("default")
 @InteractionScope   // see note above regarding this
diff --git 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/repository/RepositoryServiceDefault.java
 
b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/integration/repository/RepositoryServiceDefault.java
similarity index 90%
rename from 
core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/repository/RepositoryServiceDefault.java
rename to 
persistence/commons/src/main/java/org/apache/causeway/persistence/commons/integration/repository/RepositoryServiceDefault.java
index a70776e9f8..65d86d3641 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/repository/RepositoryServiceDefault.java
+++ 
b/persistence/commons/src/main/java/org/apache/causeway/persistence/commons/integration/repository/RepositoryServiceDefault.java
@@ -16,19 +16,23 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.causeway.core.runtimeservices.repository;
+package org.apache.causeway.persistence.commons.integration.repository;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
+import java.util.concurrent.Callable;
 import java.util.function.Predicate;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.Priority;
 import javax.inject.Named;
 
+import 
org.apache.causeway.persistence.commons.CausewayModulePersistenceCommons;
+
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.lang.Nullable;
 import org.springframework.stereotype.Service;
@@ -53,7 +57,6 @@ import 
org.apache.causeway.core.metamodel.object.MmEntityUtils;
 import org.apache.causeway.core.metamodel.object.MmUnwrapUtils;
 import org.apache.causeway.core.metamodel.objectmanager.ObjectBulkLoader;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
-import 
org.apache.causeway.core.runtimeservices.CausewayModuleCoreRuntimeServices;
 
 import lombok.Getter;
 import lombok.NonNull;
@@ -61,7 +64,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.val;
 
 @Service
-@Named(CausewayModuleCoreRuntimeServices.NAMESPACE + 
".RepositoryServiceDefault")
+@Named(CausewayModulePersistenceCommons.NAMESPACE + 
".RepositoryServiceDefault")
 @Priority(PriorityPrecedence.EARLY)
 @Qualifier("Default")
 @RequiredArgsConstructor
@@ -81,7 +84,9 @@ implements RepositoryService, HasMetaModelContext {
 
     @PostConstruct
     public void init() {
-        val disableAutoFlush = 
causewayConfiguration.getCore().getRuntimeServices().getRepositoryService().isDisableAutoFlush();
+        val disableAutoFlush =
+                
causewayConfiguration.getPersistence().getCommons().getRepositoryService().isDisableAutoFlush()
 ||
+                
causewayConfiguration.getCore().getRuntimeServices().getRepositoryService().isDisableAutoFlush();
         this.autoFlush = !disableAutoFlush;
     }
 
@@ -165,9 +170,20 @@ implements RepositoryService, HasMetaModelContext {
                 .collect(Collectors.toCollection(ArrayList::new));
     }
 
+    private static final ThreadLocal<Boolean> autoFlushSuppressed = 
ThreadLocal.withInitial(() -> false);
+    public static void suppressAutoFlush(Runnable runnable) {
+        Boolean onEntry = autoFlushSuppressed.get();
+        try {
+            autoFlushSuppressed.set(true);
+            runnable.run();
+        } finally {
+            autoFlushSuppressed.set(onEntry);
+        }
+    }
+
     @Override
     public <T> List<T> allMatches(final Query<T> query) {
-        if(autoFlush) {
+        if(autoFlush && !autoFlushSuppressed.get()) {
             transactionService.flushTransaction();
         }
         return submitQuery(query);

Reply via email to