Skip to content

Commit

Permalink
fix: use readonly transaction template where possible, spring-project…
Browse files Browse the repository at this point in the history
  • Loading branch information
mkoertgen committed Oct 18, 2024
1 parent b200971 commit f6e4113
Showing 1 changed file with 46 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ public long count(String cypherQuery, Map<String, Object> parameters) {
return transactionTemplateReadOnly.execute(tx -> {
PreparedQuery<Long> preparedQuery = PreparedQuery.queryFor(Long.class).withCypherQuery(cypherQuery)
.withParameters(parameters).build();
return toExecutableQuery(preparedQuery).getRequiredSingleResult();
return toQuery(preparedQuery, true).getRequiredSingleResult();
});
}

Expand All @@ -230,45 +230,46 @@ private <T> List<T> doFindAll(Class<T> domainType, @Nullable Class<?> resultType
return transactionTemplateReadOnly
.execute(tx -> {
Neo4jPersistentEntity<?> entityMetaData = neo4jMappingContext.getRequiredPersistentEntity(domainType);
return createExecutableQuery(domainType, resultType, QueryFragmentsAndParameters.forFindAll(entityMetaData))
return createExecutableQuery(
domainType, resultType, QueryFragmentsAndParameters.forFindAll(entityMetaData), true)
.getResults();
});
}

@Override
public <T> List<T> findAll(Statement statement, Class<T> domainType) {
return transactionTemplateReadOnly
.execute(tx -> createExecutableQuery(domainType, statement).getResults());
.execute(tx -> createExecutableQuery(domainType, statement, true).getResults());
}

@Override
public <T> List<T> findAll(Statement statement, Map<String, Object> parameters, Class<T> domainType) {
return transactionTemplateReadOnly
.execute(tx -> createExecutableQuery(domainType, null, statement, parameters).getResults());
.execute(tx -> createExecutableQuery(domainType, null, statement, parameters, true).getResults());
}

@Override
public <T> Optional<T> findOne(Statement statement, Map<String, Object> parameters, Class<T> domainType) {
return transactionTemplateReadOnly
.execute(tx -> createExecutableQuery(domainType, null, statement, parameters).getSingleResult());
.execute(tx -> createExecutableQuery(domainType, null, statement, parameters, true).getSingleResult());
}

@Override
public <T> List<T> findAll(String cypherQuery, Class<T> domainType) {
return transactionTemplateReadOnly
.execute(tx -> createExecutableQuery(domainType, cypherQuery).getResults());
.execute(tx -> createExecutableQuery(domainType, cypherQuery, true).getResults());
}

@Override
public <T> List<T> findAll(String cypherQuery, Map<String, Object> parameters, Class<T> domainType) {
return transactionTemplateReadOnly
.execute(tx -> createExecutableQuery(domainType, null, cypherQuery, parameters).getResults());
.execute(tx -> createExecutableQuery(domainType, null, cypherQuery, parameters, true).getResults());
}

@Override
public <T> Optional<T> findOne(String cypherQuery, Map<String, Object> parameters, Class<T> domainType) {
return transactionTemplateReadOnly
.execute(tx -> createExecutableQuery(domainType, null, cypherQuery, parameters).getSingleResult());
.execute(tx -> createExecutableQuery(domainType, null, cypherQuery, parameters, true).getSingleResult());
}

@Override
Expand All @@ -288,9 +289,10 @@ <T, R> List<R> doFind(@Nullable String cypherQuery, @Nullable Map<String, Object
ExecutableQuery<T> executableQuery;
if (queryFragmentsAndParameters == null) {
executableQuery = createExecutableQuery(domainType, resultType, cypherQuery,
parameters == null ? Collections.emptyMap() : parameters);
parameters == null ? Collections.emptyMap() : parameters,
true);
} else {
executableQuery = createExecutableQuery(domainType, resultType, queryFragmentsAndParameters);
executableQuery = createExecutableQuery(domainType, resultType, queryFragmentsAndParameters, true);
}
intermediaResults = switch (fetchType) {
case ALL -> executableQuery.getResults();
Expand Down Expand Up @@ -341,7 +343,8 @@ public <T> Optional<T> findById(Object id, Class<T> domainType) {

return createExecutableQuery(domainType, null,
QueryFragmentsAndParameters.forFindById(entityMetaData,
convertIdValues(entityMetaData.getRequiredIdProperty(), id)))
convertIdValues(entityMetaData.getRequiredIdProperty(), id)),
true)
.getSingleResult();
});
}
Expand All @@ -354,7 +357,8 @@ public <T> List<T> findAllById(Iterable<?> ids, Class<T> domainType) {

return createExecutableQuery(domainType, null,
QueryFragmentsAndParameters.forFindByAllId(
entityMetaData, convertIdValues(entityMetaData.getRequiredIdProperty(), ids)))
entityMetaData, convertIdValues(entityMetaData.getRequiredIdProperty(), ids)),
true)
.getResults();
});
}
Expand Down Expand Up @@ -697,7 +701,7 @@ public <T> void deleteByIdWithVersion(Object id, Class<T> domainType, Neo4jPersi
parameters.put(nameOfParameter, convertIdValues(entityMetaData.getRequiredIdProperty(), id));
parameters.put(Constants.NAME_OF_VERSION_PARAM, versionValue);

createExecutableQuery(domainType, null, statement, parameters).getSingleResult().orElseThrow(
createExecutableQuery(domainType, null, statement, parameters, false).getSingleResult().orElseThrow(
() -> new OptimisticLockingFailureException(OPTIMISTIC_LOCKING_ERROR_MESSAGE)
);

Expand Down Expand Up @@ -744,21 +748,24 @@ public void deleteAll(Class<?> domainType) {
});
}

private <T> ExecutableQuery<T> createExecutableQuery(Class<T> domainType, Statement statement) {
return createExecutableQuery(domainType, null, statement, Collections.emptyMap());
private <T> ExecutableQuery<T> createExecutableQuery(Class<T> domainType, Statement statement, boolean readOnly) {
return createExecutableQuery(domainType, null, statement, Collections.emptyMap(), readOnly);
}

private <T> ExecutableQuery<T> createExecutableQuery(Class<T> domainType, String cypherQuery) {
return createExecutableQuery(domainType, null, cypherQuery, Collections.emptyMap());
private <T> ExecutableQuery<T> createExecutableQuery(Class<T> domainType, String cypherQuery, boolean readOnly) {
return createExecutableQuery(domainType, null, cypherQuery, Collections.emptyMap(), readOnly);
}

private <T> ExecutableQuery<T> createExecutableQuery(Class<T> domainType, @Nullable Class<?> resultType, Statement statement, Map<String, Object> parameters) {
private <T> ExecutableQuery<T> createExecutableQuery(Class<T> domainType, @Nullable Class<?> resultType, Statement statement, Map<String, Object> parameters, boolean readOnly) {

return createExecutableQuery(domainType, resultType, renderer.render(statement), TemplateSupport.mergeParameters(statement, parameters));
return createExecutableQuery(domainType, resultType, renderer.render(statement), TemplateSupport.mergeParameters(statement, parameters), readOnly);
}

private <T> ExecutableQuery<T> createExecutableQuery(Class<T> domainType, @Nullable Class<?> resultType, @Nullable String cypherStatement,
Map<String, Object> parameters) {
private <T> ExecutableQuery<T> createExecutableQuery(
Class<T> domainType, @Nullable Class<?> resultType,
@Nullable String cypherStatement,
Map<String, Object> parameters,
boolean readOnly) {

Supplier<BiFunction<TypeSystem, MapAccessor, ?>> mappingFunction = TemplateSupport
.getAndDecorateMappingFunction(neo4jMappingContext, domainType, resultType);
Expand All @@ -768,7 +775,7 @@ private <T> ExecutableQuery<T> createExecutableQuery(Class<T> domainType, @Nulla
.usingMappingFunction(mappingFunction)
.build();

return toExecutableQuery(preparedQuery);
return toQuery(preparedQuery, readOnly);
}

/**
Expand Down Expand Up @@ -1191,26 +1198,31 @@ public void setTransactionManager(@Nullable PlatformTransactionManager transacti
public <T> ExecutableQuery<T> toExecutableQuery(Class<T> domainType,
QueryFragmentsAndParameters queryFragmentsAndParameters) {

return createExecutableQuery(domainType, null, queryFragmentsAndParameters);
return createExecutableQuery(domainType, null, queryFragmentsAndParameters, false);
}


private <T> ExecutableQuery<T> createExecutableQuery(Class<T> domainType, @Nullable Class<?> resultType,
QueryFragmentsAndParameters queryFragmentsAndParameters) {
private <T> ExecutableQuery<T> createExecutableQuery(
Class<T> domainType, @Nullable Class<?> resultType,
QueryFragmentsAndParameters queryFragmentsAndParameters,
boolean readOnly) {

Supplier<BiFunction<TypeSystem, MapAccessor, ?>> mappingFunction = TemplateSupport
.getAndDecorateMappingFunction(neo4jMappingContext, domainType, resultType);
PreparedQuery<T> preparedQuery = PreparedQuery.queryFor(domainType)
.withQueryFragmentsAndParameters(queryFragmentsAndParameters)
.usingMappingFunction(mappingFunction)
.build();
return toExecutableQuery(preparedQuery);
return toQuery(preparedQuery, readOnly);
}

@Override
public <T> ExecutableQuery<T> toExecutableQuery(PreparedQuery<T> preparedQuery) {
return toQuery(preparedQuery, false);
}

return new DefaultExecutableQuery<>(preparedQuery);
private <T> ExecutableQuery<T> toQuery(PreparedQuery<T> preparedQuery, boolean readOnly) {
return new DefaultExecutableQuery<>(preparedQuery, readOnly);
}

@Override
Expand Down Expand Up @@ -1255,14 +1267,17 @@ String render(Statement statement) {
final class DefaultExecutableQuery<T> implements ExecutableQuery<T> {

private final PreparedQuery<T> preparedQuery;
private final TransactionTemplate txTemplate;

DefaultExecutableQuery(PreparedQuery<T> preparedQuery) {
DefaultExecutableQuery(PreparedQuery<T> preparedQuery, boolean readOnly) {
this.preparedQuery = preparedQuery;
this.txTemplate = readOnly ? transactionTemplateReadOnly : transactionTemplate;
}


@SuppressWarnings("unchecked")
public List<T> getResults() {
return transactionTemplate
return txTemplate
.execute(tx -> {
Collection<T> all = createFetchSpec().map(Neo4jClient.RecordFetchSpec::all).orElse(Collections.emptyList());
if (preparedQuery.resultsHaveBeenAggregated()) {
Expand All @@ -1274,7 +1289,7 @@ public List<T> getResults() {

@SuppressWarnings("unchecked")
public Optional<T> getSingleResult() {
return transactionTemplate.execute(tx -> {
return txTemplate.execute(tx -> {
try {
Optional<T> one = createFetchSpec().flatMap(Neo4jClient.RecordFetchSpec::one);
if (preparedQuery.resultsHaveBeenAggregated()) {
Expand All @@ -1291,7 +1306,7 @@ public Optional<T> getSingleResult() {

@SuppressWarnings("unchecked")
public T getRequiredSingleResult() {
return transactionTemplate.execute(tx -> {
return txTemplate.execute(tx -> {
Optional<T> one = createFetchSpec().flatMap(Neo4jClient.RecordFetchSpec::one);
if (preparedQuery.resultsHaveBeenAggregated()) {
one = one.map(aggregatedResults -> ((LinkedHashSet<T>) aggregatedResults).iterator().next());
Expand Down

0 comments on commit f6e4113

Please sign in to comment.