Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue/2953 #2962

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 toExecutableQuery(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) {
mkoertgen marked this conversation as resolved.
Show resolved Hide resolved
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 toExecutableQuery(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 readOnlyTransaction) {

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 toExecutableQuery(preparedQuery, readOnlyTransaction);
}

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

return new DefaultExecutableQuery<>(preparedQuery);
private <T> ExecutableQuery<T> toExecutableQuery(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
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,9 @@ public BookmarkCapture bookmarkCapture() {
public PlatformTransactionManager transactionManager(Driver driver, DatabaseSelectionProvider databaseNameProvider) {

BookmarkCapture bookmarkCapture = bookmarkCapture();
return new Neo4jTransactionManager(driver, databaseNameProvider, Neo4jBookmarkManager.create(bookmarkCapture));
Neo4jTransactionManager transactionManager = new Neo4jTransactionManager(driver, databaseNameProvider, Neo4jBookmarkManager.create(bookmarkCapture));
transactionManager.setValidateExistingTransaction(true);
return transactionManager;
}

@Override
Expand Down