diff --git a/pom.xml b/pom.xml
index 66d67801a..07b91bff0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,7 +84,11 @@
spring.data.neo4j
17
2.3.1
+ 5.8.0
+ 1.0.0
+ 3.0.2
2021.0.1
+ 2.2.0
3.1.4
3.7.1
${java.version}
@@ -92,6 +96,7 @@
2.17.3
4.4.41
3.0.1
+ 6.0.0
${project.build.directory}/docs
UTF-8
Arabba-SR11
@@ -102,22 +107,14 @@
${skipTests}
4.0.0-SNAPSHOT
- 2.2.0
-
- org.neo4j
- neo4j-cypher-dsl-bom
- ${cypher-dsl.version}
- pom
- import
-
com.google.code.findbugs
jsr305
- 3.0.2
+ ${jsr305.version}
com.tngtech.archunit
@@ -131,9 +128,9 @@
test
- org.junit-pioneer
- junit-pioneer
- ${junit-pioneer.version}
+ io.projectreactor.tools
+ blockhound
+ ${blockhound.version}
io.r2dbc
@@ -161,18 +158,35 @@
net.java.dev.jna
jna
- 5.8.0
+ ${jna.version}
org.apiguardian
apiguardian-api
${apiguardian.version}
+
+ org.jspecify
+ jspecify
+ ${jspecify.version}
+
+
+ org.junit-pioneer
+ junit-pioneer
+ ${junit-pioneer.version}
+
org.neo4j
neo4j
${neo4j.version}
+
+ org.neo4j
+ neo4j-cypher-dsl-bom
+ ${cypher-dsl.version}
+ pom
+ import
+
org.neo4j.driver
neo4j-java-driver
@@ -191,7 +205,7 @@
org.osgi
org.osgi.core
- 6.0.0
+ ${org.osgi.core.version}
org.slf4j
@@ -210,11 +224,6 @@
pom
import
-
- io.projectreactor.tools
- blockhound
- ${blockhound.version}
-
@@ -279,6 +288,11 @@
test
true
+
+ io.projectreactor.tools
+ blockhound
+ test
+
io.r2dbc
r2dbc-h2
@@ -341,6 +355,11 @@
kotlinx-coroutines-reactor
true
+
+ org.junit-pioneer
+ junit-pioneer
+ test
+
org.neo4j
neo4j-cypher-dsl
@@ -415,28 +434,18 @@
-
- io.projectreactor.tools
- blockhound
- test
-
-
- org.junit-pioneer
- junit-pioneer
- test
-
- spring-snapshot
- https://repo.spring.io/snapshot
-
- true
-
false
+
+ true
+
+ spring-snapshot
+ https://repo.spring.io/snapshot
spring-milestone
@@ -643,31 +652,6 @@
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
-
- java-compile
-
-
- -Xlint:all,-options,-path
-
-
-
-
-
- java-test-compile
-
- true
-
-
-
-
org.apache.maven.plugins
maven-resources-plugin
@@ -689,8 +673,8 @@
- src/main/antora/resources/antora-resources
true
+ src/main/antora/resources/antora-resources
diff --git a/src/main/java/org/springframework/data/neo4j/aot/Neo4jManagedTypesBeanRegistrationAotProcessor.java b/src/main/java/org/springframework/data/neo4j/aot/Neo4jManagedTypesBeanRegistrationAotProcessor.java
index 76008745a..115931e7f 100644
--- a/src/main/java/org/springframework/data/neo4j/aot/Neo4jManagedTypesBeanRegistrationAotProcessor.java
+++ b/src/main/java/org/springframework/data/neo4j/aot/Neo4jManagedTypesBeanRegistrationAotProcessor.java
@@ -15,17 +15,17 @@
*/
package org.springframework.data.neo4j.aot;
+import org.jspecify.annotations.Nullable;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.core.ResolvableType;
import org.springframework.data.aot.ManagedTypesBeanRegistrationAotProcessor;
-import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
* @author Gerrit Meier
* @since 7.0.0
*/
-public class Neo4jManagedTypesBeanRegistrationAotProcessor extends ManagedTypesBeanRegistrationAotProcessor {
+public final class Neo4jManagedTypesBeanRegistrationAotProcessor extends ManagedTypesBeanRegistrationAotProcessor {
public Neo4jManagedTypesBeanRegistrationAotProcessor() {
setModuleIdentifier("neo4j");
@@ -36,7 +36,7 @@ public class Neo4jManagedTypesBeanRegistrationAotProcessor extends ManagedTypesB
return isNeo4jManagedTypes(beanType) || super.isMatch(beanType, beanName);
}
- protected boolean isNeo4jManagedTypes(@Nullable Class> beanType) {
+ boolean isNeo4jManagedTypes(@Nullable Class> beanType) {
return beanType != null && ClassUtils.isAssignable(Neo4jManagedTypes.class, beanType);
}
diff --git a/src/main/java/org/springframework/data/neo4j/aot/Neo4jRuntimeHints.java b/src/main/java/org/springframework/data/neo4j/aot/Neo4jRuntimeHints.java
index 12dd3c0bf..10f03ba12 100644
--- a/src/main/java/org/springframework/data/neo4j/aot/Neo4jRuntimeHints.java
+++ b/src/main/java/org/springframework/data/neo4j/aot/Neo4jRuntimeHints.java
@@ -15,6 +15,7 @@
*/
package org.springframework.data.neo4j.aot;
+import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
@@ -34,7 +35,6 @@ import org.springframework.data.neo4j.repository.support.SimpleNeo4jRepository;
import org.springframework.data.neo4j.repository.support.SimpleReactiveNeo4jRepository;
import org.springframework.data.querydsl.QuerydslUtils;
import org.springframework.data.util.ReactiveWrappers;
-import org.springframework.lang.Nullable;
import java.util.Arrays;
diff --git a/src/main/java/org/springframework/data/neo4j/aot/package-info.java b/src/main/java/org/springframework/data/neo4j/aot/package-info.java
new file mode 100644
index 000000000..d7bad8269
--- /dev/null
+++ b/src/main/java/org/springframework/data/neo4j/aot/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package org.springframework.data.neo4j.aot;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/src/main/java/org/springframework/data/neo4j/config/AbstractNeo4jConfig.java b/src/main/java/org/springframework/data/neo4j/config/AbstractNeo4jConfig.java
index 717ec65f9..568cd36ec 100644
--- a/src/main/java/org/springframework/data/neo4j/config/AbstractNeo4jConfig.java
+++ b/src/main/java/org/springframework/data/neo4j/config/AbstractNeo4jConfig.java
@@ -16,6 +16,7 @@
package org.springframework.data.neo4j.config;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import org.neo4j.driver.Driver;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
@@ -30,7 +31,6 @@ import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager;
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
import org.springframework.data.neo4j.repository.config.Neo4jRepositoryConfigurationExtension;
-import org.springframework.lang.Nullable;
import org.springframework.transaction.PlatformTransactionManager;
/**
@@ -65,11 +65,11 @@ public abstract class AbstractNeo4jConfig extends Neo4jConfigurationSupport {
* @return A imperative Neo4j client.
*/
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_CLIENT_BEAN_NAME)
- public Neo4jClient neo4jClient(Driver driver, DatabaseSelectionProvider databaseSelectionProvider) {
+ public Neo4jClient neo4jClient(Driver driver, @Nullable DatabaseSelectionProvider databaseSelectionProvider) {
return Neo4jClient.with(driver)
.withDatabaseSelectionProvider(databaseSelectionProvider)
- .withUserSelectionProvider(getUserSelectionProvider())
+ .withUserSelectionProvider(this.userSelectionProviders.getIfUnique())
.withNeo4jBookmarkManager(getBootBookmarkManager())
.build();
}
@@ -78,11 +78,6 @@ public abstract class AbstractNeo4jConfig extends Neo4jConfigurationSupport {
return this.bookmarkManagerProviders.getIfAvailable(Neo4jBookmarkManager::create);
}
- @Nullable
- private UserSelectionProvider getUserSelectionProvider() {
- return this.userSelectionProviders == null ? null : this.userSelectionProviders.getIfUnique();
- }
-
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_TEMPLATE_BEAN_NAME)
public Neo4jOperations neo4jTemplate(final Neo4jClient neo4jClient, final Neo4jMappingContext mappingContext) {
@@ -97,12 +92,12 @@ public abstract class AbstractNeo4jConfig extends Neo4jConfigurationSupport {
* @return A platform transaction manager
*/
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME)
- public PlatformTransactionManager transactionManager(Driver driver, DatabaseSelectionProvider databaseSelectionProvider) {
+ public PlatformTransactionManager transactionManager(Driver driver, @Nullable DatabaseSelectionProvider databaseSelectionProvider) {
return Neo4jTransactionManager
.with(driver)
.withDatabaseSelectionProvider(databaseSelectionProvider)
- .withUserSelectionProvider(getUserSelectionProvider())
+ .withUserSelectionProvider(this.userSelectionProviders.getIfUnique())
.withBookmarkManager(getBootBookmarkManager())
.build();
}
diff --git a/src/main/java/org/springframework/data/neo4j/config/AbstractReactiveNeo4jConfig.java b/src/main/java/org/springframework/data/neo4j/config/AbstractReactiveNeo4jConfig.java
index 74534ac14..c6f854061 100644
--- a/src/main/java/org/springframework/data/neo4j/config/AbstractReactiveNeo4jConfig.java
+++ b/src/main/java/org/springframework/data/neo4j/config/AbstractReactiveNeo4jConfig.java
@@ -16,6 +16,7 @@
package org.springframework.data.neo4j.config;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import org.neo4j.driver.Driver;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
@@ -29,7 +30,6 @@ import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager;
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;
import org.springframework.data.neo4j.repository.config.ReactiveNeo4jRepositoryConfigurationExtension;
-import org.springframework.lang.Nullable;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.ReactiveTransactionManager;
diff --git a/src/main/java/org/springframework/data/neo4j/config/Neo4jConfigurationSupport.java b/src/main/java/org/springframework/data/neo4j/config/Neo4jConfigurationSupport.java
index f86494dc2..b017fe8cb 100644
--- a/src/main/java/org/springframework/data/neo4j/config/Neo4jConfigurationSupport.java
+++ b/src/main/java/org/springframework/data/neo4j/config/Neo4jConfigurationSupport.java
@@ -90,18 +90,4 @@ abstract class Neo4jConfigurationSupport {
return Neo4jEntityScanner.get().scan(getMappingBasePackages());
}
-
- /**
- * Scans the given base package for entities, i.e. Neo4j specific types annotated with {@link Node}.
- *
- * @param basePackage must not be {@literal null}.
- * @return found entities in the package to scan.
- * @throws ClassNotFoundException if the given class cannot be loaded by the class loader.
- * @deprecated since 6.0.2 Use {@link Neo4jEntityScanner} instead.
- */
- @Deprecated
- protected final Set> scanForEntities(String basePackage) throws ClassNotFoundException {
-
- return Neo4jEntityScanner.get().scan(basePackage);
- }
}
diff --git a/src/main/java/org/springframework/data/neo4j/config/Neo4jEntityScanner.java b/src/main/java/org/springframework/data/neo4j/config/Neo4jEntityScanner.java
index 216a1fd94..03a13e86a 100644
--- a/src/main/java/org/springframework/data/neo4j/config/Neo4jEntityScanner.java
+++ b/src/main/java/org/springframework/data/neo4j/config/Neo4jEntityScanner.java
@@ -23,6 +23,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
@@ -31,7 +32,6 @@ import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.RelationshipProperties;
-import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -55,7 +55,8 @@ public final class Neo4jEntityScanner {
return new Neo4jEntityScanner(resourceLoader);
}
- private @Nullable final ResourceLoader resourceLoader;
+ @Nullable
+ private final ResourceLoader resourceLoader;
/**
* Create a new {@link Neo4jEntityScanner} instance.
@@ -121,8 +122,7 @@ public final class Neo4jEntityScanner {
* @param resourceLoader an optional {@link ResourceLoader} to use
* @return a {@link ClassPathScanningCandidateComponentProvider} suitable to scan for Neo4j entities
*/
- private static ClassPathScanningCandidateComponentProvider createClassPathScanningCandidateComponentProvider(
- @Nullable ResourceLoader resourceLoader) {
+ private static ClassPathScanningCandidateComponentProvider createClassPathScanningCandidateComponentProvider(@Nullable ResourceLoader resourceLoader) {
ClassPathScanningCandidateComponentProvider delegate = new ClassPathScanningCandidateComponentProvider(false);
if (resourceLoader != null) {
diff --git a/src/main/java/org/springframework/data/neo4j/config/package-info.java b/src/main/java/org/springframework/data/neo4j/config/package-info.java
index 8aa6d1f9d..ee8cb7d7d 100644
--- a/src/main/java/org/springframework/data/neo4j/config/package-info.java
+++ b/src/main/java/org/springframework/data/neo4j/config/package-info.java
@@ -5,7 +5,7 @@
The package provides some additional annotations that enable auditing.
*
*/
-@NonNullApi
+@NullMarked
package org.springframework.data.neo4j.config;
-import org.springframework.lang.NonNullApi;
+import org.jspecify.annotations.NullMarked;
diff --git a/src/main/java/org/springframework/data/neo4j/core/DatabaseSelection.java b/src/main/java/org/springframework/data/neo4j/core/DatabaseSelection.java
index 4fe182656..015f5448c 100644
--- a/src/main/java/org/springframework/data/neo4j/core/DatabaseSelection.java
+++ b/src/main/java/org/springframework/data/neo4j/core/DatabaseSelection.java
@@ -18,7 +18,7 @@ package org.springframework.data.neo4j.core;
import java.util.Objects;
import org.apiguardian.api.API;
-import org.springframework.lang.Nullable;
+import org.jspecify.annotations.Nullable;
/**
* A value holder indicating a database selection based on an optional name. {@literal null} indicates to let the server
@@ -33,7 +33,8 @@ public final class DatabaseSelection {
private static final DatabaseSelection DEFAULT_DATABASE_NAME = new DatabaseSelection(null);
- @Nullable private final String value;
+ @Nullable
+ private final String value;
public static DatabaseSelection undecided() {
diff --git a/src/main/java/org/springframework/data/neo4j/core/DefaultNeo4jClient.java b/src/main/java/org/springframework/data/neo4j/core/DefaultNeo4jClient.java
index f2884c944..a0362e6f5 100644
--- a/src/main/java/org/springframework/data/neo4j/core/DefaultNeo4jClient.java
+++ b/src/main/java/org/springframework/data/neo4j/core/DefaultNeo4jClient.java
@@ -26,6 +26,7 @@ import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.jspecify.annotations.Nullable;
import org.neo4j.driver.Bookmark;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Query;
@@ -49,7 +50,6 @@ import org.springframework.data.neo4j.core.support.BookmarkManagerReference;
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager;
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionUtils;
-import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -64,8 +64,10 @@ import org.springframework.util.StringUtils;
final class DefaultNeo4jClient implements Neo4jClient, ApplicationContextAware {
private final Driver driver;
- private @Nullable final DatabaseSelectionProvider databaseSelectionProvider;
- private @Nullable final UserSelectionProvider userSelectionProvider;
+ @Nullable
+ private final DatabaseSelectionProvider databaseSelectionProvider;
+ @Nullable
+ private final UserSelectionProvider userSelectionProvider;
private final ConversionService conversionService;
private final Neo4jPersistenceExceptionTranslator persistenceExceptionTranslator = new Neo4jPersistenceExceptionTranslator();
@@ -276,7 +278,7 @@ final class DefaultNeo4jClient implements Neo4jClient, ApplicationContextAware {
}
@Override
- public OngoingBindSpec bind(T value) {
+ public OngoingBindSpec bind(@Nullable T value) {
return new DefaultOngoingBindSpec<>(value);
}
@@ -314,7 +316,8 @@ final class DefaultNeo4jClient implements Neo4jClient, ApplicationContextAware {
class DefaultOngoingBindSpec implements OngoingBindSpec {
- @Nullable private final T value;
+ @Nullable
+ private final T value;
DefaultOngoingBindSpec(@Nullable T value) {
this.value = value;
@@ -360,7 +363,7 @@ final class DefaultNeo4jClient implements Neo4jClient, ApplicationContextAware {
}
@Override
- public OngoingBindSpec bind(T value) {
+ public OngoingBindSpec bind(@Nullable T value) {
return DefaultRunnableSpec.this.bind(value);
}
@@ -395,7 +398,7 @@ final class DefaultNeo4jClient implements Neo4jClient, ApplicationContextAware {
}
@Override
- public OngoingBindSpec bind(T value) {
+ public OngoingBindSpec bind(@Nullable T value) {
return DefaultRunnableSpec.this.bind(value);
}
@@ -410,7 +413,6 @@ final class DefaultNeo4jClient implements Neo4jClient, ApplicationContextAware {
private final DatabaseSelection databaseSelection;
- @Nullable
private final UserSelection impersonatedUser;
private final RunnableStatement runnableStatement;
@@ -418,7 +420,7 @@ final class DefaultNeo4jClient implements Neo4jClient, ApplicationContextAware {
private BiFunction mappingFunction;
DefaultRecordFetchSpec(DatabaseSelection databaseSelection,
- @Nullable UserSelection impersonatedUser,
+ UserSelection impersonatedUser,
RunnableStatement runnableStatement,
BiFunction mappingFunction) {
@@ -501,7 +503,6 @@ final class DefaultNeo4jClient implements Neo4jClient, ApplicationContextAware {
private DatabaseSelection databaseSelection;
- @Nullable
private UserSelection impersonatedUser;
private final Function> callback;
@@ -513,7 +514,7 @@ final class DefaultNeo4jClient implements Neo4jClient, ApplicationContextAware {
}
@Override
- public RunnableDelegation in(@Nullable String targetDatabase) {
+ public RunnableDelegation in(String targetDatabase) {
this.databaseSelection = resolveTargetDatabaseName(targetDatabase);
return this;
diff --git a/src/main/java/org/springframework/data/neo4j/core/DefaultReactiveNeo4jClient.java b/src/main/java/org/springframework/data/neo4j/core/DefaultReactiveNeo4jClient.java
index dc188aad9..7ea9847fb 100644
--- a/src/main/java/org/springframework/data/neo4j/core/DefaultReactiveNeo4jClient.java
+++ b/src/main/java/org/springframework/data/neo4j/core/DefaultReactiveNeo4jClient.java
@@ -15,6 +15,7 @@
*/
package org.springframework.data.neo4j.core;
+import org.jspecify.annotations.Nullable;
import org.neo4j.driver.Bookmark;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Query;
@@ -38,7 +39,6 @@ import org.springframework.data.neo4j.core.support.BookmarkManagerReference;
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager;
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionUtils;
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;
-import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -66,8 +66,10 @@ import java.util.function.Supplier;
final class DefaultReactiveNeo4jClient implements ReactiveNeo4jClient, ApplicationContextAware {
private final Driver driver;
- private @Nullable final ReactiveDatabaseSelectionProvider databaseSelectionProvider;
- private @Nullable final ReactiveUserSelectionProvider userSelectionProvider;
+ @Nullable
+ private final ReactiveDatabaseSelectionProvider databaseSelectionProvider;
+ @Nullable
+ private final ReactiveUserSelectionProvider userSelectionProvider;
private final ConversionService conversionService;
private final Neo4jPersistenceExceptionTranslator persistenceExceptionTranslator = new Neo4jPersistenceExceptionTranslator();
@@ -241,7 +243,7 @@ final class DefaultReactiveNeo4jClient implements ReactiveNeo4jClient, Applicati
}
@Override
- public Neo4jClient.OngoingBindSpec bind(T value) {
+ public Neo4jClient.OngoingBindSpec bind(@Nullable T value) {
return new DefaultOngoingBindSpec<>(value);
}
@@ -267,12 +269,13 @@ final class DefaultReactiveNeo4jClient implements ReactiveNeo4jClient, Applicati
@Override
public Mono run() {
- return new DefaultRecordFetchSpec<>(databaseSelection, userSelection, cypherSupplier, this.parameters, null).run();
+ return new DefaultRecordFetchSpec<>(databaseSelection, userSelection, cypherSupplier, this.parameters, (t, r) -> null).run();
}
class DefaultOngoingBindSpec implements Neo4jClient.OngoingBindSpec {
- @Nullable private final T value;
+ @Nullable
+ private final T value;
DefaultOngoingBindSpec(@Nullable T value) {
this.value = value;
@@ -318,7 +321,7 @@ final class DefaultReactiveNeo4jClient implements ReactiveNeo4jClient, Applicati
}
@Override
- public Neo4jClient.OngoingBindSpec bind(T value) {
+ public Neo4jClient.OngoingBindSpec bind(@Nullable T value) {
return DefaultRunnableSpec.this.bind(value);
}
@@ -353,7 +356,7 @@ final class DefaultReactiveNeo4jClient implements ReactiveNeo4jClient, Applicati
}
@Override
- public Neo4jClient.OngoingBindSpec bind(T value) {
+ public Neo4jClient.OngoingBindSpec bind(@Nullable T value) {
return DefaultRunnableSpec.this.bind(value);
}
@@ -376,8 +379,7 @@ final class DefaultReactiveNeo4jClient implements ReactiveNeo4jClient, Applicati
private BiFunction mappingFunction;
- DefaultRecordFetchSpec(Mono databaseSelection, Mono userSelection, Supplier cypherSupplier, NamedParameters parameters,
- @Nullable BiFunction mappingFunction) {
+ DefaultRecordFetchSpec(Mono databaseSelection, Mono userSelection, Supplier cypherSupplier, NamedParameters parameters, BiFunction mappingFunction) {
this.databaseSelection = databaseSelection;
this.userSelection = userSelection;
@@ -477,7 +479,7 @@ final class DefaultReactiveNeo4jClient implements ReactiveNeo4jClient, Applicati
}
@Override
- public RunnableDelegation in(@Nullable @SuppressWarnings("HiddenField") String targetDatabase) {
+ public RunnableDelegation in(@SuppressWarnings("HiddenField") String targetDatabase) {
this.databaseSelection = resolveTargetDatabaseName(targetDatabase);
return this;
diff --git a/src/main/java/org/springframework/data/neo4j/core/DynamicLabels.java b/src/main/java/org/springframework/data/neo4j/core/DynamicLabels.java
index 2be8dc1e1..560fe6a90 100644
--- a/src/main/java/org/springframework/data/neo4j/core/DynamicLabels.java
+++ b/src/main/java/org/springframework/data/neo4j/core/DynamicLabels.java
@@ -21,12 +21,12 @@ import java.util.Collections;
import java.util.List;
import java.util.function.UnaryOperator;
+import org.jspecify.annotations.Nullable;
import org.neo4j.cypherdsl.core.Cypher;
import org.neo4j.cypherdsl.core.Node;
import org.neo4j.cypherdsl.core.StatementBuilder.OngoingMatchAndUpdate;
import org.springframework.data.neo4j.core.mapping.Constants;
import org.springframework.data.neo4j.core.mapping.NodeDescription;
-import org.springframework.lang.Nullable;
/**
* Decorator for an ongoing update statement that removes obsolete dynamic labels and adds new ones.
@@ -42,9 +42,9 @@ final class DynamicLabels implements UnaryOperator {
private final List oldLabels;
private final List newLabels;
- DynamicLabels(@Nullable NodeDescription> nodeDescription, Collection oldLabels, Collection newLabels) {
+ DynamicLabels(@Nullable NodeDescription> nodeDescription, Collection oldLabels, @Nullable Collection newLabels) {
this.oldLabels = new ArrayList<>(oldLabels);
- this.newLabels = new ArrayList<>(newLabels);
+ this.newLabels = (newLabels != null) ? new ArrayList<>(newLabels) : List.of();
this.rootNode = Cypher.anyNode(Constants.NAME_OF_TYPED_ROOT_NODE.apply(nodeDescription));
}
diff --git a/src/main/java/org/springframework/data/neo4j/core/FluentFindOperation.java b/src/main/java/org/springframework/data/neo4j/core/FluentFindOperation.java
index 73be3a6a6..cd5b72b79 100644
--- a/src/main/java/org/springframework/data/neo4j/core/FluentFindOperation.java
+++ b/src/main/java/org/springframework/data/neo4j/core/FluentFindOperation.java
@@ -21,9 +21,9 @@ import java.util.Map;
import java.util.Optional;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import org.neo4j.cypherdsl.core.Statement;
import org.springframework.data.neo4j.repository.query.QueryFragmentsAndParameters;
-import org.springframework.lang.Nullable;
/**
* {@link FluentFindOperation} allows creation and execution of Neo4j find operations in a fluent API style.
@@ -105,7 +105,7 @@ public interface FluentFindOperation {
* @return new instance of {@link TerminatingFind}.
* @throws IllegalArgumentException if query is {@literal null}.
*/
- TerminatingFind matching(String query, @Nullable Map parameter);
+ TerminatingFind matching(String query, Map parameter);
/**
* Creates an executable query based on fragments and parameters. Hardly useful outside framework-code
@@ -136,7 +136,7 @@ public interface FluentFindOperation {
* @return new instance of {@link TerminatingFind}.
* @throws IllegalArgumentException if statement is {@literal null}.
*/
- TerminatingFind matching(Statement statement, @Nullable Map parameter);
+ TerminatingFind matching(Statement statement, Map parameter);
/**
* Set the filter {@link Statement statement} to be used.
diff --git a/src/main/java/org/springframework/data/neo4j/core/FluentOperationSupport.java b/src/main/java/org/springframework/data/neo4j/core/FluentOperationSupport.java
index 0c963eaf5..57a69344d 100644
--- a/src/main/java/org/springframework/data/neo4j/core/FluentOperationSupport.java
+++ b/src/main/java/org/springframework/data/neo4j/core/FluentOperationSupport.java
@@ -19,6 +19,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
+import org.jspecify.annotations.Nullable;
import org.neo4j.cypherdsl.core.Statement;
import org.springframework.data.neo4j.repository.query.QueryFragmentsAndParameters;
import org.springframework.util.Assert;
@@ -51,12 +52,15 @@ final class FluentOperationSupport implements FluentFindOperation, FluentSaveOpe
private final Neo4jTemplate template;
private final Class> domainType;
private final Class returnType;
+ @Nullable
private final String query;
+ @Nullable
private final Map parameters;
+ @Nullable
private final QueryFragmentsAndParameters queryFragmentsAndParameters;
- ExecutableFindSupport(Neo4jTemplate template, Class> domainType, Class returnType, String query,
- Map parameters) {
+ ExecutableFindSupport(Neo4jTemplate template, Class> domainType, Class returnType, @Nullable String query,
+ @Nullable Map parameters) {
this.template = template;
this.domainType = domainType;
this.returnType = returnType;
@@ -65,7 +69,7 @@ final class FluentOperationSupport implements FluentFindOperation, FluentSaveOpe
this.queryFragmentsAndParameters = null;
}
- ExecutableFindSupport(Neo4jTemplate template, Class> domainType, Class returnType, QueryFragmentsAndParameters queryFragmentsAndParameters) {
+ ExecutableFindSupport(Neo4jTemplate template, Class> domainType, Class returnType, @Nullable QueryFragmentsAndParameters queryFragmentsAndParameters) {
this.template = template;
this.domainType = domainType;
this.returnType = returnType;
@@ -107,6 +111,7 @@ final class FluentOperationSupport implements FluentFindOperation, FluentSaveOpe
}
@Override
+ @Nullable
public T oneValue() {
List result = doFind(TemplateSupport.FetchType.ONE);
@@ -149,7 +154,7 @@ final class FluentOperationSupport implements FluentFindOperation, FluentSaveOpe
List result = doSave(Collections.singleton(instance));
if (result.isEmpty()) {
- return null;
+ throw new IllegalStateException("Instance was not saved");
}
return result.get(0);
}
diff --git a/src/main/java/org/springframework/data/neo4j/core/NamedParameters.java b/src/main/java/org/springframework/data/neo4j/core/NamedParameters.java
index 7f9eebba9..ba9a0c758 100644
--- a/src/main/java/org/springframework/data/neo4j/core/NamedParameters.java
+++ b/src/main/java/org/springframework/data/neo4j/core/NamedParameters.java
@@ -24,11 +24,11 @@ import java.util.Map;
import java.util.stream.Collectors;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import org.neo4j.cypherdsl.core.Cypher;
import org.neo4j.driver.Value;
import org.springframework.data.neo4j.core.mapping.Constants;
import org.springframework.data.neo4j.core.mapping.MapValueWrapper;
-import org.springframework.lang.Nullable;
/**
* @author Michael J. Simons
@@ -141,7 +141,7 @@ final class NamedParameters {
}
@Nullable
- private static String formatValue(@Nullable Object value) {
+ private static String formatValue(Object value) {
if (value == null) {
return null;
} else if (value instanceof String) {
diff --git a/src/main/java/org/springframework/data/neo4j/core/Neo4jClient.java b/src/main/java/org/springframework/data/neo4j/core/Neo4jClient.java
index c885ae023..88e59555d 100644
--- a/src/main/java/org/springframework/data/neo4j/core/Neo4jClient.java
+++ b/src/main/java/org/springframework/data/neo4j/core/Neo4jClient.java
@@ -15,6 +15,7 @@
*/
package org.springframework.data.neo4j.core;
+import java.io.Serial;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
@@ -25,6 +26,7 @@ import java.util.function.Supplier;
import org.apache.commons.logging.LogFactory;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import org.neo4j.driver.Driver;
import org.neo4j.driver.QueryRunner;
import org.neo4j.driver.Record;
@@ -33,7 +35,6 @@ import org.neo4j.driver.types.TypeSystem;
import org.springframework.core.log.LogAccessor;
import org.springframework.data.neo4j.core.convert.Neo4jConversions;
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager;
-import org.springframework.lang.Nullable;
/**
* Definition of a modern Neo4j client.
@@ -127,7 +128,7 @@ public interface Neo4jClient {
* @return The builder
* @since 6.3.3
*/
- public Builder withNeo4jConversions(Neo4jConversions neo4jConversions) {
+ public Builder withNeo4jConversions(@Nullable Neo4jConversions neo4jConversions) {
this.neo4jConversions = neo4jConversions;
return this;
}
@@ -141,7 +142,7 @@ public interface Neo4jClient {
* @return The builder
* @since 7.1.2
*/
- public Builder withNeo4jBookmarkManager(Neo4jBookmarkManager bookmarkManager) {
+ public Builder withNeo4jBookmarkManager(@Nullable Neo4jBookmarkManager bookmarkManager) {
this.bookmarkManager = bookmarkManager;
return this;
}
@@ -266,7 +267,7 @@ public interface Neo4jClient {
* @param targetDatabase selected database to use. A {@literal null} value indicates the default database.
* @return A runnable query specification that is now bound to a given database.
*/
- RunnableSpecBoundToDatabase in(@Nullable String targetDatabase);
+ RunnableSpecBoundToDatabase in(String targetDatabase);
/**
* Pins the previously defined query to an impersonated user. A value of {@literal null} chooses the user owning
@@ -275,7 +276,7 @@ public interface Neo4jClient {
* @param asUser The name of the user to impersonate. A {@literal null} value indicates the connected user.
* @return A runnable query specification that is now bound to a given database.
*/
- RunnableSpecBoundToUser asUser(@Nullable String asUser);
+ RunnableSpecBoundToUser asUser(String asUser);
}
/**
@@ -408,7 +409,7 @@ public interface Neo4jClient {
* @param targetDatabase selected database to use. A {@literal null} value indicates the default database.
* @return An ongoing delegation
*/
- RunnableDelegation in(@Nullable String targetDatabase);
+ RunnableDelegation in(String targetDatabase);
}
/**
@@ -451,6 +452,9 @@ public interface Neo4jClient {
@API(status = API.Status.STABLE, since = "6.1.5")
class IllegalDatabaseNameException extends IllegalArgumentException {
+ @Serial
+ private static final long serialVersionUID = 3496326026855204643L;
+
private final String illegalDatabaseName;
private IllegalDatabaseNameException(String illegalDatabaseName) {
diff --git a/src/main/java/org/springframework/data/neo4j/core/Neo4jOperations.java b/src/main/java/org/springframework/data/neo4j/core/Neo4jOperations.java
index 5f158415d..f6839382d 100644
--- a/src/main/java/org/springframework/data/neo4j/core/Neo4jOperations.java
+++ b/src/main/java/org/springframework/data/neo4j/core/Neo4jOperations.java
@@ -21,13 +21,13 @@ import java.util.Optional;
import java.util.function.BiPredicate;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import org.neo4j.cypherdsl.core.Statement;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.neo4j.core.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.repository.NoResultException;
import org.springframework.data.neo4j.repository.query.QueryFragmentsAndParameters;
-import org.springframework.lang.Nullable;
/**
* Specifies operations one can perform on a database, based on an Domain Type.
@@ -207,6 +207,7 @@ public interface Neo4jOperations {
* @return the saved instance.
* @since 6.3
*/
+ @Nullable
default T saveAs(T instance, BiPredicate includeProperty) {
throw new UnsupportedOperationException();
}
@@ -220,6 +221,7 @@ public interface Neo4jOperations {
* @return the saved, projected instance.
* @since 6.1
*/
+ @Nullable
default R saveAs(T instance, Class resultType) {
throw new UnsupportedOperationException();
}
diff --git a/src/main/java/org/springframework/data/neo4j/core/Neo4jPersistenceExceptionTranslator.java b/src/main/java/org/springframework/data/neo4j/core/Neo4jPersistenceExceptionTranslator.java
index 2d801dc3c..18923b9f8 100644
--- a/src/main/java/org/springframework/data/neo4j/core/Neo4jPersistenceExceptionTranslator.java
+++ b/src/main/java/org/springframework/data/neo4j/core/Neo4jPersistenceExceptionTranslator.java
@@ -23,6 +23,7 @@ import java.util.function.BiFunction;
import org.apache.commons.logging.LogFactory;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import org.neo4j.driver.exceptions.AuthenticationException;
import org.neo4j.driver.exceptions.ClientException;
import org.neo4j.driver.exceptions.DatabaseException;
@@ -61,6 +62,7 @@ public final class Neo4jPersistenceExceptionTranslator implements PersistenceExc
private static final Map>> ERROR_CODE_MAPPINGS;
@Override
+ @Nullable
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
if (ex instanceof DataAccessException) {
diff --git a/src/main/java/org/springframework/data/neo4j/core/Neo4jTemplate.java b/src/main/java/org/springframework/data/neo4j/core/Neo4jTemplate.java
index fd07edba7..5b18b7fb4 100644
--- a/src/main/java/org/springframework/data/neo4j/core/Neo4jTemplate.java
+++ b/src/main/java/org/springframework/data/neo4j/core/Neo4jTemplate.java
@@ -40,6 +40,8 @@ import java.util.stream.Collectors;
import org.apache.commons.logging.LogFactory;
import org.apiguardian.api.API;
+import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
import org.neo4j.cypherdsl.core.Condition;
import org.neo4j.cypherdsl.core.Cypher;
import org.neo4j.cypherdsl.core.FunctionInvocation;
@@ -49,7 +51,6 @@ import org.neo4j.cypherdsl.core.Statement;
import org.neo4j.cypherdsl.core.renderer.Configuration;
import org.neo4j.cypherdsl.core.renderer.Renderer;
import org.neo4j.driver.Value;
-import org.neo4j.driver.Values;
import org.neo4j.driver.exceptions.NoSuchRecordException;
import org.neo4j.driver.summary.ResultSummary;
import org.neo4j.driver.types.Entity;
@@ -96,11 +97,11 @@ import org.springframework.data.neo4j.repository.query.QueryFragmentsAndParamete
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.ProjectionInformation;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
-import org.springframework.data.util.TypeInformation;
-import org.springframework.lang.NonNull;
-import org.springframework.lang.Nullable;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;
@@ -135,18 +136,22 @@ public final class Neo4jTemplate implements
private final CypherGenerator cypherGenerator;
+ @Nullable
private ClassLoader beanClassLoader;
private EventSupport eventSupport;
+ @Nullable
private ProjectionFactory projectionFactory;
private Renderer renderer;
private Function elementIdOrIdFunction;
+ @Nullable
private TransactionTemplate transactionTemplate;
+ @Nullable
private TransactionTemplate transactionTemplateReadOnly;
public Neo4jTemplate(Neo4jClient neo4jClient) {
@@ -185,6 +190,18 @@ public final class Neo4jTemplate implements
return Objects.requireNonNull(this.projectionFactory, "Projection support for the Neo4j template is only available when the template is a proper and fully initialized Spring bean.");
}
+ private T execute(TransactionCallback action) throws TransactionException {
+ return Objects.requireNonNull(Objects.requireNonNull(this.transactionTemplate).execute(action));
+ }
+
+ private T executeReadOnly(TransactionCallback action) throws TransactionException {
+ return Objects.requireNonNull(Objects.requireNonNull(this.transactionTemplateReadOnly).execute(action));
+ }
+
+ private void executeWithoutResult(Consumer action) throws TransactionException {
+ Objects.requireNonNull(this.transactionTemplate).executeWithoutResult(action);
+ }
+
@Override
public long count(Class> domainType) {
@@ -213,7 +230,7 @@ public final class Neo4jTemplate implements
@Override
public long count(String cypherQuery, Map parameters) {
- return transactionTemplateReadOnly.execute(tx -> {
+ return executeReadOnly(tx -> {
PreparedQuery preparedQuery = PreparedQuery.queryFor(Long.class).withCypherQuery(cypherQuery)
.withParameters(parameters).build();
return toExecutableQuery(preparedQuery, true).getRequiredSingleResult();
@@ -227,8 +244,7 @@ public final class Neo4jTemplate implements
}
private List doFindAll(Class domainType, @Nullable Class> resultType) {
- return transactionTemplateReadOnly
- .execute(tx -> {
+ return executeReadOnly(tx -> {
Neo4jPersistentEntity> entityMetaData = neo4jMappingContext.getRequiredPersistentEntity(domainType);
return createExecutableQuery(
domainType, resultType, QueryFragmentsAndParameters.forFindAll(entityMetaData), true)
@@ -238,61 +254,54 @@ public final class Neo4jTemplate implements
@Override
public List findAll(Statement statement, Class domainType) {
- return transactionTemplateReadOnly
- .execute(tx -> createExecutableQuery(domainType, statement, true).getResults());
+ return executeReadOnly(tx -> createExecutableQuery(domainType, statement, true).getResults());
}
@Override
public List findAll(Statement statement, Map parameters, Class domainType) {
- return transactionTemplateReadOnly
- .execute(tx -> createExecutableQuery(domainType, null, statement, parameters, true).getResults());
+ return executeReadOnly(tx -> createExecutableQuery(domainType, null, statement, parameters, true).getResults());
}
@Override
public Optional findOne(Statement statement, Map parameters, Class domainType) {
- return transactionTemplateReadOnly
- .execute(tx -> createExecutableQuery(domainType, null, statement, parameters, true).getSingleResult());
+ return executeReadOnly(tx -> createExecutableQuery(domainType, null, statement, parameters, true).getSingleResult());
}
@Override
public List findAll(String cypherQuery, Class domainType) {
- return transactionTemplateReadOnly
- .execute(tx -> createExecutableQuery(domainType, cypherQuery, true).getResults());
+ return executeReadOnly(tx -> createExecutableQuery(domainType, cypherQuery, true).getResults());
}
@Override
public List findAll(String cypherQuery, Map parameters, Class domainType) {
- return transactionTemplateReadOnly
- .execute(tx -> createExecutableQuery(domainType, null, cypherQuery, parameters, true).getResults());
+ return executeReadOnly(tx -> createExecutableQuery(domainType, null, cypherQuery, parameters, true).getResults());
}
@Override
public Optional findOne(String cypherQuery, Map parameters, Class domainType) {
- return transactionTemplateReadOnly
- .execute(tx -> createExecutableQuery(domainType, null, cypherQuery, parameters, true).getSingleResult());
+ return executeReadOnly(tx -> createExecutableQuery(domainType, null, cypherQuery, parameters, true).getSingleResult());
}
@Override
public ExecutableFind find(Class domainType) {
- return transactionTemplateReadOnly
- .execute(tx -> new FluentOperationSupport(this).find(domainType));
+ return new FluentOperationSupport(this).find(domainType);
}
@SuppressWarnings("unchecked")
List doFind(@Nullable String cypherQuery, @Nullable Map parameters, Class domainType, Class resultType, TemplateSupport.FetchType fetchType, @Nullable QueryFragmentsAndParameters queryFragmentsAndParameters) {
- return transactionTemplateReadOnly.execute(tx -> {
- List intermediaResults = Collections.emptyList();
+ return executeReadOnly(tx -> {
+ List intermediaResults;
if (cypherQuery == null && queryFragmentsAndParameters == null && fetchType == TemplateSupport.FetchType.ALL) {
intermediaResults = doFindAll(domainType, resultType);
} else {
ExecutableQuery executableQuery;
- if (queryFragmentsAndParameters == null) {
+ if (queryFragmentsAndParameters == null && cypherQuery != null) {
executableQuery = createExecutableQuery(domainType, resultType, cypherQuery,
parameters == null ? Collections.emptyMap() : parameters,
true);
} else {
- executableQuery = createExecutableQuery(domainType, resultType, queryFragmentsAndParameters, true);
+ executableQuery = createExecutableQuery(domainType, resultType, Objects.requireNonNull(queryFragmentsAndParameters), true);
}
intermediaResults = switch (fetchType) {
case ALL -> executableQuery.getResults();
@@ -327,7 +336,7 @@ public final class Neo4jTemplate implements
Neo4jPersistentEntity> entityMetaData = neo4jMappingContext.getRequiredPersistentEntity(domainType);
QueryFragmentsAndParameters fragmentsAndParameters = QueryFragmentsAndParameters
- .forExistsById(entityMetaData, convertIdValues(entityMetaData.getRequiredIdProperty(), id));
+ .forExistsById(entityMetaData, TemplateSupport.convertIdValues(this.neo4jMappingContext, entityMetaData.getRequiredIdProperty(), id));
Statement statement = fragmentsAndParameters.getQueryFragments().toStatement();
Map parameters = fragmentsAndParameters.getParameters();
@@ -337,13 +346,12 @@ public final class Neo4jTemplate implements
@Override
public Optional findById(Object id, Class domainType) {
- return transactionTemplateReadOnly
- .execute(tx -> {
+ return executeReadOnly(tx -> {
Neo4jPersistentEntity> entityMetaData = neo4jMappingContext.getRequiredPersistentEntity(domainType);
return createExecutableQuery(domainType, null,
QueryFragmentsAndParameters.forFindById(entityMetaData,
- convertIdValues(entityMetaData.getRequiredIdProperty(), id)),
+ TemplateSupport.convertIdValues(this.neo4jMappingContext, entityMetaData.getRequiredIdProperty(), id)),
true)
.getSingleResult();
});
@@ -351,62 +359,44 @@ public final class Neo4jTemplate implements
@Override
public List findAllById(Iterable> ids, Class domainType) {
- return transactionTemplateReadOnly
- .execute(tx -> {
+ return executeReadOnly(tx -> {
Neo4jPersistentEntity> entityMetaData = neo4jMappingContext.getRequiredPersistentEntity(domainType);
return createExecutableQuery(domainType, null,
QueryFragmentsAndParameters.forFindByAllId(
- entityMetaData, convertIdValues(entityMetaData.getRequiredIdProperty(), ids)),
+ entityMetaData, TemplateSupport.convertIdValues(this.neo4jMappingContext, entityMetaData.getRequiredIdProperty(), ids)),
true)
.getResults();
});
}
- private Object convertIdValues(@Nullable Neo4jPersistentProperty idProperty, @Nullable Object idValues) {
-
- if (idProperty != null && ((Neo4jPersistentEntity>) idProperty.getOwner()).isUsingInternalIds()) {
- return idValues;
- }
-
- if (idValues != null) {
- return neo4jMappingContext.getConversionService().writeValue(idValues, TypeInformation.of(idValues.getClass()), idProperty == null ? null : idProperty.getOptionalConverter());
- } else if (idProperty != null) {
- return neo4jMappingContext.getConversionService().writeValue(idValues, idProperty.getTypeInformation(), idProperty.getOptionalConverter());
- } else {
- // Not much we can convert here
- return Values.NULL;
- }
- }
-
@Override
public T save(T instance) {
- return transactionTemplate
- .execute(tx -> saveImpl(instance, Collections.emptySet(), null));
+ return execute(tx -> saveImpl(instance, Collections.emptySet(), null));
}
@Override
+ @Nullable
public T saveAs(T instance, BiPredicate includeProperty) {
if (instance == null) {
return null;
}
- return transactionTemplate
- .execute(tx -> saveImpl(instance, TemplateSupport.computeIncludedPropertiesFromPredicate(this.neo4jMappingContext, instance.getClass(), includeProperty), null));
+ return execute(tx -> saveImpl(instance, TemplateSupport.computeIncludedPropertiesFromPredicate(this.neo4jMappingContext, instance.getClass(), includeProperty), null));
}
@Override
+ @Nullable
public R saveAs(T instance, Class resultType) {
- return transactionTemplate.execute(tx -> {
+ Assert.notNull(resultType, "ResultType must not be null");
+ if (instance == null) {
+ return null;
+ }
- Assert.notNull(resultType, "ResultType must not be null");
-
- if (instance == null) {
- return null;
- }
+ return execute(tx -> {
if (resultType.equals(instance.getClass())) {
return resultType.cast(save(instance));
@@ -427,14 +417,14 @@ public final class Neo4jTemplate implements
}
Neo4jPersistentEntity> entityMetaData = neo4jMappingContext.getRequiredPersistentEntity(savedInstance.getClass());
- Neo4jPersistentProperty idProperty = entityMetaData.getIdProperty();
+ Neo4jPersistentProperty idProperty = entityMetaData.getRequiredIdProperty();
PersistentPropertyAccessor propertyAccessor = entityMetaData.getPropertyAccessor(savedInstance);
return localProjectionFactory.createProjection(resultType,
- this.findById(propertyAccessor.getProperty(idProperty), savedInstance.getClass()).get());
+ this.findById(Objects.requireNonNull(propertyAccessor.getProperty(idProperty)), savedInstance.getClass()).orElseThrow());
});
}
- private T saveImpl(T instance, @Nullable Collection includedProperties, @Nullable NestedRelationshipProcessingStateMachine stateMachine) {
+ private T saveImpl(T instance, Collection includedProperties, @Nullable NestedRelationshipProcessingStateMachine stateMachine) {
if (stateMachine != null && stateMachine.hasProcessedValue(instance)) {
return instance;
@@ -471,8 +461,10 @@ public final class Neo4jTemplate implements
if (!entityMetaData.isUsingDeprecatedInternalId() && TemplateSupport.rendererRendersElementId(renderer)) {
return IdentitySupport.getElementId(node);
}
- return node.id();
- }).get();
+ @SuppressWarnings("deprecation")
+ var id = node.id();
+ return id;
+ }).orElseThrow();
PersistentPropertyAccessor propertyAccessor = entityMetaData.getPropertyAccessor(entityToBeSaved);
TemplateSupport.setGeneratedIdIfNecessary(entityMetaData, propertyAccessor, elementId, newOrUpdatedNode);
@@ -498,7 +490,7 @@ public final class Neo4jTemplate implements
Neo4jPersistentProperty idProperty = entityMetaData.getRequiredIdProperty();
Neo4jClient.RunnableSpec runnableQuery = neo4jClient
.query(() -> renderer.render(cypherGenerator.createStatementReturningDynamicLabels(entityMetaData)))
- .bind(convertIdValues(idProperty, propertyAccessor.getProperty(idProperty)))
+ .bind(TemplateSupport.convertIdValues(this.neo4jMappingContext, idProperty, propertyAccessor.getProperty(idProperty)))
.to(Constants.NAME_OF_ID).bind(entityMetaData.getStaticLabels())
.to(Constants.NAME_OF_STATIC_LABELS_PARAM);
@@ -516,8 +508,7 @@ public final class Neo4jTemplate implements
@Override
public List saveAll(Iterable instances) {
- return transactionTemplate
- .execute(tx -> saveAllImpl(instances, Collections.emptySet(), null));
+ return execute(tx -> saveAllImpl(instances, Collections.emptySet(), null));
}
private boolean requiresSingleStatements(boolean heterogeneousCollection, Neo4jPersistentEntity> entityMetaData) {
@@ -544,7 +535,7 @@ public final class Neo4jTemplate implements
Class> domainClass = types.iterator().next();
Collection pps = includeProperty == null ?
- includedProperties :
+ Objects.requireNonNullElseGet(includedProperties, List::of) :
TemplateSupport.computeIncludedPropertiesFromPredicate(this.neo4jMappingContext, domainClass,
includeProperty);
@@ -593,8 +584,8 @@ public final class Neo4jTemplate implements
return entitiesToBeSaved.stream().map(t -> {
PersistentPropertyAccessor propertyAccessor = entityMetaData.getPropertyAccessor(t.modifiedInstance);
Neo4jPersistentProperty idProperty = entityMetaData.getRequiredIdProperty();
- Object id = convertIdValues(idProperty, propertyAccessor.getProperty(idProperty));
- String internalId = idToInternalIdMapping.get(id);
+ Object id = TemplateSupport.convertIdValues(this.neo4jMappingContext, idProperty, propertyAccessor.getProperty(idProperty));
+ String internalId = Objects.requireNonNull(idToInternalIdMapping.get(id));
stateMachine.registerInitialObject(t.originalInstance, internalId);
return this.processRelations(entityMetaData, propertyAccessor, t.wasNew, stateMachine, TemplateSupport.computeIncludePropertyPredicate(pps, entityMetaData));
}).collect(Collectors.toList());
@@ -603,17 +594,15 @@ public final class Neo4jTemplate implements
@Override
public List saveAllAs(Iterable instances, BiPredicate includeProperty) {
- return transactionTemplate
- .execute(tx -> saveAllImpl(instances, null, includeProperty));
+ return execute(tx -> saveAllImpl(instances, null, includeProperty));
}
@Override
public List saveAllAs(Iterable instances, Class resultType) {
- return transactionTemplate
- .execute(tx -> {
+ Assert.notNull(resultType, "ResultType must not be null");
- Assert.notNull(resultType, "ResultType must not be null");
+ return execute(tx -> {
Class> commonElementType = TemplateSupport.findCommonElementType(instances);
@@ -645,7 +634,7 @@ public final class Neo4jTemplate implements
}
Neo4jPersistentEntity> entityMetaData = neo4jMappingContext.getRequiredPersistentEntity(commonElementType);
- Neo4jPersistentProperty idProperty = entityMetaData.getIdProperty();
+ Neo4jPersistentProperty idProperty = entityMetaData.getRequiredIdProperty();
List