@@ -216,7 +216,7 @@ public long count(String cypherQuery, Map<String, Object> parameters) {
216216 return transactionTemplateReadOnly .execute (tx -> {
217217 PreparedQuery <Long > preparedQuery = PreparedQuery .queryFor (Long .class ).withCypherQuery (cypherQuery )
218218 .withParameters (parameters ).build ();
219- return toExecutableQuery (preparedQuery ).getRequiredSingleResult ();
219+ return toExecutableQuery (preparedQuery , true ).getRequiredSingleResult ();
220220 });
221221 }
222222
@@ -230,45 +230,46 @@ private <T> List<T> doFindAll(Class<T> domainType, @Nullable Class<?> resultType
230230 return transactionTemplateReadOnly
231231 .execute (tx -> {
232232 Neo4jPersistentEntity <?> entityMetaData = neo4jMappingContext .getRequiredPersistentEntity (domainType );
233- return createExecutableQuery (domainType , resultType , QueryFragmentsAndParameters .forFindAll (entityMetaData ))
233+ return createExecutableQuery (
234+ domainType , resultType , QueryFragmentsAndParameters .forFindAll (entityMetaData ), true )
234235 .getResults ();
235236 });
236237 }
237238
238239 @ Override
239240 public <T > List <T > findAll (Statement statement , Class <T > domainType ) {
240241 return transactionTemplateReadOnly
241- .execute (tx -> createExecutableQuery (domainType , statement ).getResults ());
242+ .execute (tx -> createExecutableQuery (domainType , statement , true ).getResults ());
242243 }
243244
244245 @ Override
245246 public <T > List <T > findAll (Statement statement , Map <String , Object > parameters , Class <T > domainType ) {
246247 return transactionTemplateReadOnly
247- .execute (tx -> createExecutableQuery (domainType , null , statement , parameters ).getResults ());
248+ .execute (tx -> createExecutableQuery (domainType , null , statement , parameters , true ).getResults ());
248249 }
249250
250251 @ Override
251252 public <T > Optional <T > findOne (Statement statement , Map <String , Object > parameters , Class <T > domainType ) {
252253 return transactionTemplateReadOnly
253- .execute (tx -> createExecutableQuery (domainType , null , statement , parameters ).getSingleResult ());
254+ .execute (tx -> createExecutableQuery (domainType , null , statement , parameters , true ).getSingleResult ());
254255 }
255256
256257 @ Override
257258 public <T > List <T > findAll (String cypherQuery , Class <T > domainType ) {
258259 return transactionTemplateReadOnly
259- .execute (tx -> createExecutableQuery (domainType , cypherQuery ).getResults ());
260+ .execute (tx -> createExecutableQuery (domainType , cypherQuery , true ).getResults ());
260261 }
261262
262263 @ Override
263264 public <T > List <T > findAll (String cypherQuery , Map <String , Object > parameters , Class <T > domainType ) {
264265 return transactionTemplateReadOnly
265- .execute (tx -> createExecutableQuery (domainType , null , cypherQuery , parameters ).getResults ());
266+ .execute (tx -> createExecutableQuery (domainType , null , cypherQuery , parameters , true ).getResults ());
266267 }
267268
268269 @ Override
269270 public <T > Optional <T > findOne (String cypherQuery , Map <String , Object > parameters , Class <T > domainType ) {
270271 return transactionTemplateReadOnly
271- .execute (tx -> createExecutableQuery (domainType , null , cypherQuery , parameters ).getSingleResult ());
272+ .execute (tx -> createExecutableQuery (domainType , null , cypherQuery , parameters , true ).getSingleResult ());
272273 }
273274
274275 @ Override
@@ -288,9 +289,10 @@ <T, R> List<R> doFind(@Nullable String cypherQuery, @Nullable Map<String, Object
288289 ExecutableQuery <T > executableQuery ;
289290 if (queryFragmentsAndParameters == null ) {
290291 executableQuery = createExecutableQuery (domainType , resultType , cypherQuery ,
291- parameters == null ? Collections .emptyMap () : parameters );
292+ parameters == null ? Collections .emptyMap () : parameters ,
293+ true );
292294 } else {
293- executableQuery = createExecutableQuery (domainType , resultType , queryFragmentsAndParameters );
295+ executableQuery = createExecutableQuery (domainType , resultType , queryFragmentsAndParameters , true );
294296 }
295297 intermediaResults = switch (fetchType ) {
296298 case ALL -> executableQuery .getResults ();
@@ -341,7 +343,8 @@ public <T> Optional<T> findById(Object id, Class<T> domainType) {
341343
342344 return createExecutableQuery (domainType , null ,
343345 QueryFragmentsAndParameters .forFindById (entityMetaData ,
344- convertIdValues (entityMetaData .getRequiredIdProperty (), id )))
346+ convertIdValues (entityMetaData .getRequiredIdProperty (), id )),
347+ true )
345348 .getSingleResult ();
346349 });
347350 }
@@ -354,7 +357,8 @@ public <T> List<T> findAllById(Iterable<?> ids, Class<T> domainType) {
354357
355358 return createExecutableQuery (domainType , null ,
356359 QueryFragmentsAndParameters .forFindByAllId (
357- entityMetaData , convertIdValues (entityMetaData .getRequiredIdProperty (), ids )))
360+ entityMetaData , convertIdValues (entityMetaData .getRequiredIdProperty (), ids )),
361+ true )
358362 .getResults ();
359363 });
360364 }
@@ -697,7 +701,7 @@ public <T> void deleteByIdWithVersion(Object id, Class<T> domainType, Neo4jPersi
697701 parameters .put (nameOfParameter , convertIdValues (entityMetaData .getRequiredIdProperty (), id ));
698702 parameters .put (Constants .NAME_OF_VERSION_PARAM , versionValue );
699703
700- createExecutableQuery (domainType , null , statement , parameters ).getSingleResult ().orElseThrow (
704+ createExecutableQuery (domainType , null , statement , parameters , false ).getSingleResult ().orElseThrow (
701705 () -> new OptimisticLockingFailureException (OPTIMISTIC_LOCKING_ERROR_MESSAGE )
702706 );
703707
@@ -744,21 +748,24 @@ public void deleteAll(Class<?> domainType) {
744748 });
745749 }
746750
747- private <T > ExecutableQuery <T > createExecutableQuery (Class <T > domainType , Statement statement ) {
748- return createExecutableQuery (domainType , null , statement , Collections .emptyMap ());
751+ private <T > ExecutableQuery <T > createExecutableQuery (Class <T > domainType , Statement statement , boolean readOnly ) {
752+ return createExecutableQuery (domainType , null , statement , Collections .emptyMap (), readOnly );
749753 }
750754
751- private <T > ExecutableQuery <T > createExecutableQuery (Class <T > domainType , String cypherQuery ) {
752- return createExecutableQuery (domainType , null , cypherQuery , Collections .emptyMap ());
755+ private <T > ExecutableQuery <T > createExecutableQuery (Class <T > domainType , String cypherQuery , boolean readOnly ) {
756+ return createExecutableQuery (domainType , null , cypherQuery , Collections .emptyMap (), readOnly );
753757 }
754758
755- private <T > ExecutableQuery <T > createExecutableQuery (Class <T > domainType , @ Nullable Class <?> resultType , Statement statement , Map <String , Object > parameters ) {
759+ private <T > ExecutableQuery <T > createExecutableQuery (Class <T > domainType , @ Nullable Class <?> resultType , Statement statement , Map <String , Object > parameters , boolean readOnly ) {
756760
757- return createExecutableQuery (domainType , resultType , renderer .render (statement ), TemplateSupport .mergeParameters (statement , parameters ));
761+ return createExecutableQuery (domainType , resultType , renderer .render (statement ), TemplateSupport .mergeParameters (statement , parameters ), readOnly );
758762 }
759763
760- private <T > ExecutableQuery <T > createExecutableQuery (Class <T > domainType , @ Nullable Class <?> resultType , @ Nullable String cypherStatement ,
761- Map <String , Object > parameters ) {
764+ private <T > ExecutableQuery <T > createExecutableQuery (
765+ Class <T > domainType , @ Nullable Class <?> resultType ,
766+ @ Nullable String cypherStatement ,
767+ Map <String , Object > parameters ,
768+ boolean readOnly ) {
762769
763770 Supplier <BiFunction <TypeSystem , MapAccessor , ?>> mappingFunction = TemplateSupport
764771 .getAndDecorateMappingFunction (neo4jMappingContext , domainType , resultType );
@@ -768,7 +775,7 @@ private <T> ExecutableQuery<T> createExecutableQuery(Class<T> domainType, @Nulla
768775 .usingMappingFunction (mappingFunction )
769776 .build ();
770777
771- return toExecutableQuery (preparedQuery );
778+ return toExecutableQuery (preparedQuery , readOnly );
772779 }
773780
774781 /**
@@ -1191,26 +1198,31 @@ public void setTransactionManager(@Nullable PlatformTransactionManager transacti
11911198 public <T > ExecutableQuery <T > toExecutableQuery (Class <T > domainType ,
11921199 QueryFragmentsAndParameters queryFragmentsAndParameters ) {
11931200
1194- return createExecutableQuery (domainType , null , queryFragmentsAndParameters );
1201+ return createExecutableQuery (domainType , null , queryFragmentsAndParameters , false );
11951202 }
11961203
11971204
1198- private <T > ExecutableQuery <T > createExecutableQuery (Class <T > domainType , @ Nullable Class <?> resultType ,
1199- QueryFragmentsAndParameters queryFragmentsAndParameters ) {
1205+ private <T > ExecutableQuery <T > createExecutableQuery (
1206+ Class <T > domainType , @ Nullable Class <?> resultType ,
1207+ QueryFragmentsAndParameters queryFragmentsAndParameters ,
1208+ boolean readOnlyTransaction ) {
12001209
12011210 Supplier <BiFunction <TypeSystem , MapAccessor , ?>> mappingFunction = TemplateSupport
12021211 .getAndDecorateMappingFunction (neo4jMappingContext , domainType , resultType );
12031212 PreparedQuery <T > preparedQuery = PreparedQuery .queryFor (domainType )
12041213 .withQueryFragmentsAndParameters (queryFragmentsAndParameters )
12051214 .usingMappingFunction (mappingFunction )
12061215 .build ();
1207- return toExecutableQuery (preparedQuery );
1216+ return toExecutableQuery (preparedQuery , readOnlyTransaction );
12081217 }
12091218
12101219 @ Override
12111220 public <T > ExecutableQuery <T > toExecutableQuery (PreparedQuery <T > preparedQuery ) {
1221+ return toExecutableQuery (preparedQuery , false );
1222+ }
12121223
1213- return new DefaultExecutableQuery <>(preparedQuery );
1224+ private <T > ExecutableQuery <T > toExecutableQuery (PreparedQuery <T > preparedQuery , boolean readOnly ) {
1225+ return new DefaultExecutableQuery <>(preparedQuery , readOnly );
12141226 }
12151227
12161228 @ Override
@@ -1255,14 +1267,17 @@ String render(Statement statement) {
12551267 final class DefaultExecutableQuery <T > implements ExecutableQuery <T > {
12561268
12571269 private final PreparedQuery <T > preparedQuery ;
1270+ private final TransactionTemplate txTemplate ;
12581271
1259- DefaultExecutableQuery (PreparedQuery <T > preparedQuery ) {
1272+ DefaultExecutableQuery (PreparedQuery <T > preparedQuery , boolean readOnly ) {
12601273 this .preparedQuery = preparedQuery ;
1274+ this .txTemplate = readOnly ? transactionTemplateReadOnly : transactionTemplate ;
12611275 }
12621276
1277+
12631278 @ SuppressWarnings ("unchecked" )
12641279 public List <T > getResults () {
1265- return transactionTemplate
1280+ return txTemplate
12661281 .execute (tx -> {
12671282 Collection <T > all = createFetchSpec ().map (Neo4jClient .RecordFetchSpec ::all ).orElse (Collections .emptyList ());
12681283 if (preparedQuery .resultsHaveBeenAggregated ()) {
@@ -1274,7 +1289,7 @@ public List<T> getResults() {
12741289
12751290 @ SuppressWarnings ("unchecked" )
12761291 public Optional <T > getSingleResult () {
1277- return transactionTemplate .execute (tx -> {
1292+ return txTemplate .execute (tx -> {
12781293 try {
12791294 Optional <T > one = createFetchSpec ().flatMap (Neo4jClient .RecordFetchSpec ::one );
12801295 if (preparedQuery .resultsHaveBeenAggregated ()) {
@@ -1291,7 +1306,7 @@ public Optional<T> getSingleResult() {
12911306
12921307 @ SuppressWarnings ("unchecked" )
12931308 public T getRequiredSingleResult () {
1294- return transactionTemplate .execute (tx -> {
1309+ return txTemplate .execute (tx -> {
12951310 Optional <T > one = createFetchSpec ().flatMap (Neo4jClient .RecordFetchSpec ::one );
12961311 if (preparedQuery .resultsHaveBeenAggregated ()) {
12971312 one = one .map (aggregatedResults -> ((LinkedHashSet <T >) aggregatedResults ).iterator ().next ());
0 commit comments