GH-2640 - Introduce API for dynamic configuration of transient properties. (#2645)
This change introduces the concept of `PersistentPropertyCharacteristics` and `PersistentPropertyCharacteristicsProvider`. The latter can be registered implicitly as a `@Bean` with the mapping context or via a custom mapping context. It allows checking the properties and their owner for indicators like type and so on to treat them as transient or read only. Examples have been added to the `Neo4jMappingContextTest` and `PersistentPropertyCharacteristicsIT`. This closes #2640.
This commit is contained in:
@@ -89,7 +89,7 @@ class Neo4jCdiConfigurationSupport {
|
||||
@Produces @Singleton
|
||||
public Neo4jMappingContext neo4jMappingContext(@SuppressWarnings("CdiInjectionPointsInspection") Driver driver, @Any Instance<Neo4jConversions> neo4JConversions) {
|
||||
|
||||
return new Neo4jMappingContext(resolve(neo4JConversions), driver.defaultTypeSystem());
|
||||
return Neo4jMappingContext.builder().withNeo4jConversions(resolve(neo4JConversions)).withTypeSystem(driver.defaultTypeSystem()).build();
|
||||
}
|
||||
|
||||
@Produces @Singleton
|
||||
|
||||
@@ -61,6 +61,8 @@ final class DefaultNeo4jPersistentProperty extends AnnotationBasedPersistentProp
|
||||
|
||||
private final Lazy<Neo4jPersistentPropertyConverter<?>> customConversion;
|
||||
|
||||
private final @Nullable PersistentPropertyCharacteristics optionalCharacteristics;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AnnotationBasedPersistentProperty}.
|
||||
*
|
||||
@@ -69,7 +71,7 @@ final class DefaultNeo4jPersistentProperty extends AnnotationBasedPersistentProp
|
||||
* @param simpleTypeHolder type holder
|
||||
*/
|
||||
DefaultNeo4jPersistentProperty(Property property, PersistentEntity<?, Neo4jPersistentProperty> owner,
|
||||
Neo4jMappingContext mappingContext, SimpleTypeHolder simpleTypeHolder) {
|
||||
Neo4jMappingContext mappingContext, SimpleTypeHolder simpleTypeHolder, @Nullable PersistentPropertyCharacteristics optionalCharacteristics) {
|
||||
|
||||
super(property, owner, simpleTypeHolder);
|
||||
this.mappingContext = mappingContext;
|
||||
@@ -101,6 +103,8 @@ final class DefaultNeo4jPersistentProperty extends AnnotationBasedPersistentProp
|
||||
|
||||
return this.mappingContext.getOptionalCustomConversionsFor(this);
|
||||
});
|
||||
|
||||
this.optionalCharacteristics = optionalCharacteristics;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -308,7 +312,17 @@ final class DefaultNeo4jPersistentProperty extends AnnotationBasedPersistentProp
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
|
||||
if (optionalCharacteristics != null && optionalCharacteristics.isReadOnly() != null) {
|
||||
return Boolean.TRUE.equals(optionalCharacteristics.isReadOnly());
|
||||
}
|
||||
|
||||
Class<org.springframework.data.neo4j.core.schema.Property> typeOfAnnotation = org.springframework.data.neo4j.core.schema.Property.class;
|
||||
return isAnnotationPresent(ReadOnlyProperty.class) || (isAnnotationPresent(typeOfAnnotation) && getRequiredAnnotation(typeOfAnnotation).readOnly());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransient() {
|
||||
return this.optionalCharacteristics == null || optionalCharacteristics.isTransient() == null ?
|
||||
super.isTransient() : Boolean.TRUE.equals(optionalCharacteristics.isTransient());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ import org.springframework.data.neo4j.core.mapping.callback.EventSupport;
|
||||
import org.springframework.data.neo4j.core.schema.IdGenerator;
|
||||
import org.springframework.data.neo4j.core.schema.Node;
|
||||
import org.springframework.data.neo4j.core.schema.PostLoad;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -117,14 +118,94 @@ public final class Neo4jMappingContext extends AbstractMappingContext<Neo4jPersi
|
||||
|
||||
private boolean strict = false;
|
||||
|
||||
private final Lazy<PersistentPropertyCharacteristicsProvider> propertyCharacteristicsProvider;
|
||||
|
||||
/**
|
||||
* A builder for creating custom instances of a {@link Neo4jMappingContext}.
|
||||
* @since 6.3.7
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
private Neo4jConversions neo4jConversions;
|
||||
|
||||
@Nullable
|
||||
private TypeSystem typeSystem;
|
||||
|
||||
@Nullable
|
||||
private PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider;
|
||||
|
||||
private Builder() {
|
||||
this(new Neo4jConversions(), null, null);
|
||||
}
|
||||
|
||||
private Builder(Neo4jConversions neo4jConversions, @Nullable TypeSystem typeSystem, @Nullable PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider) {
|
||||
this.neo4jConversions = neo4jConversions;
|
||||
this.typeSystem = typeSystem;
|
||||
this.persistentPropertyCharacteristicsProvider = persistentPropertyCharacteristicsProvider;
|
||||
}
|
||||
|
||||
@SuppressWarnings("HiddenField")
|
||||
public Builder withNeo4jConversions(@Nullable Neo4jConversions neo4jConversions) {
|
||||
this.neo4jConversions = neo4jConversions;
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("HiddenField")
|
||||
public Builder withPersistentPropertyCharacteristicsProvider(@Nullable PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider) {
|
||||
this.persistentPropertyCharacteristicsProvider = persistentPropertyCharacteristicsProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("HiddenField")
|
||||
public Builder withTypeSystem(@Nullable TypeSystem typeSystem) {
|
||||
this.typeSystem = typeSystem;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Neo4jMappingContext build() {
|
||||
return new Neo4jMappingContext(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public Neo4jMappingContext() {
|
||||
|
||||
this(new Neo4jConversions());
|
||||
this(new Builder());
|
||||
}
|
||||
|
||||
public Neo4jMappingContext(Neo4jConversions neo4jConversions) {
|
||||
|
||||
this(neo4jConversions, null);
|
||||
this(new Builder(neo4jConversions, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* This API is primarily used from inside the CDI extension to configure the type system. This is necessary as
|
||||
* we don't get notified of the context via {@link #setApplicationContext(ApplicationContext applicationContext)}.
|
||||
*
|
||||
* @param neo4jConversions The conversions to be used
|
||||
* @param typeSystem The current drivers type system. If this is null, we use the default one without accessing the driver.
|
||||
* @deprecated Use {@link Neo4jMappingContext#builder()}
|
||||
*/
|
||||
@API(status = API.Status.INTERNAL, since = "6.0")
|
||||
@Deprecated
|
||||
public Neo4jMappingContext(Neo4jConversions neo4jConversions, @Nullable TypeSystem typeSystem) {
|
||||
this(new Builder(neo4jConversions, typeSystem, null));
|
||||
}
|
||||
|
||||
private Neo4jMappingContext(Builder builder) {
|
||||
|
||||
this.conversionService = new DefaultNeo4jConversionService(builder.neo4jConversions);
|
||||
this.typeSystem = builder.typeSystem == null ? InternalTypeSystem.TYPE_SYSTEM : builder.typeSystem;
|
||||
this.eventSupport = EventSupport.useExistingCallbacks(this, EntityCallbacks.create());
|
||||
|
||||
super.setSimpleTypeHolder(builder.neo4jConversions.getSimpleTypeHolder());
|
||||
|
||||
PersistentPropertyCharacteristicsProvider characteristicsProvider = builder.persistentPropertyCharacteristicsProvider;
|
||||
this.propertyCharacteristicsProvider = Lazy.of(() -> characteristicsProvider != null || this.beanFactory == null ?
|
||||
characteristicsProvider : this.beanFactory.getBeanProvider(PersistentPropertyCharacteristicsProvider.class).getIfUnique());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,22 +220,6 @@ public final class Neo4jMappingContext extends AbstractMappingContext<Neo4jPersi
|
||||
this.strict = strict;
|
||||
}
|
||||
|
||||
/**
|
||||
* This API is primarily used from inside the CDI extension to configure the type system. This is necessary as
|
||||
* we don't get notified of the context via {@link #setApplicationContext(ApplicationContext applicationContext)}.
|
||||
*
|
||||
* @param neo4jConversions The conversions to be used
|
||||
* @param typeSystem The current drivers type system. If this is null, we use the default one without accessing the driver.
|
||||
*/
|
||||
@API(status = API.Status.INTERNAL, since = "6.0")
|
||||
public Neo4jMappingContext(Neo4jConversions neo4jConversions, @Nullable TypeSystem typeSystem) {
|
||||
|
||||
this.conversionService = new DefaultNeo4jConversionService(neo4jConversions);
|
||||
this.typeSystem = typeSystem == null ? InternalTypeSystem.TYPE_SYSTEM : typeSystem;
|
||||
this.eventSupport = EventSupport.useExistingCallbacks(this, EntityCallbacks.create());
|
||||
|
||||
super.setSimpleTypeHolder(neo4jConversions.getSimpleTypeHolder());
|
||||
}
|
||||
|
||||
public Neo4jEntityConverter getEntityConverter() {
|
||||
return new DefaultNeo4jEntityConverter(INSTANTIATORS, nodeDescriptionStore, conversionService, eventSupport,
|
||||
@@ -260,7 +325,12 @@ public final class Neo4jMappingContext extends AbstractMappingContext<Neo4jPersi
|
||||
protected Neo4jPersistentProperty createPersistentProperty(Property property, Neo4jPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
|
||||
return new DefaultNeo4jPersistentProperty(property, owner, this, simpleTypeHolder);
|
||||
PersistentPropertyCharacteristics optionalCharacteristics = this.propertyCharacteristicsProvider
|
||||
.getOptional()
|
||||
.flatMap(provider -> Optional.ofNullable(provider.apply(property, owner)))
|
||||
.orElse(null);
|
||||
|
||||
return new DefaultNeo4jPersistentProperty(property, owner, this, simpleTypeHolder, optionalCharacteristics);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -278,9 +348,9 @@ public final class Neo4jMappingContext extends AbstractMappingContext<Neo4jPersi
|
||||
@Nullable
|
||||
public Neo4jPersistentEntity<?> getPersistentEntity(TypeInformation<?> typeInformation) {
|
||||
|
||||
NodeDescription<?> existingDescription = this.doGetPersistentEntity(typeInformation);
|
||||
Neo4jPersistentEntity<?> existingDescription = this.doGetPersistentEntity(typeInformation);
|
||||
if (existingDescription != null) {
|
||||
return (Neo4jPersistentEntity<?>) existingDescription;
|
||||
return existingDescription;
|
||||
}
|
||||
return super.getPersistentEntity(typeInformation);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2011-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.core.mapping;
|
||||
|
||||
import static org.apiguardian.api.API.Status.STABLE;
|
||||
|
||||
import org.apiguardian.api.API;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* The characteristics of a {@link Neo4jPersistentProperty} can diverge from what is by default derived from the annotated
|
||||
* classes. Diverging characteristics are requested by the {@link Neo4jMappingContext} prior to creating a persistent property.
|
||||
* Additional providers of characteristics may be registered with the mapping context.
|
||||
*
|
||||
* @author Michael J. Simons
|
||||
* @soundtrack Metallica - Kill 'Em All
|
||||
* @since 6.3.7
|
||||
*/
|
||||
@API(status = STABLE, since = "6.3.7")
|
||||
public interface PersistentPropertyCharacteristics {
|
||||
|
||||
/**
|
||||
* @return {@literal null} to leave the defaults, {@literal true} or {@literal false} otherwise
|
||||
*/
|
||||
@Nullable
|
||||
default Boolean isTransient() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal null} to leave the defaults, {@literal true} or {@literal false} otherwise
|
||||
*/
|
||||
@Nullable
|
||||
default Boolean isReadOnly() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Characteristics applying the defaults
|
||||
*/
|
||||
static PersistentPropertyCharacteristics useDefaults() {
|
||||
return new PersistentPropertyCharacteristics() {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Characteristics to treat a property as transient
|
||||
*/
|
||||
static PersistentPropertyCharacteristics treatAsTransient() {
|
||||
return new PersistentPropertyCharacteristics() {
|
||||
@Override
|
||||
public Boolean isTransient() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Characteristics to treat a property as transient
|
||||
*/
|
||||
static PersistentPropertyCharacteristics treatAsReadOnly() {
|
||||
return new PersistentPropertyCharacteristics() {
|
||||
@Override
|
||||
public Boolean isReadOnly() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2011-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.core.mapping;
|
||||
|
||||
import static org.apiguardian.api.API.Status.STABLE;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.apiguardian.api.API;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
|
||||
/**
|
||||
* An instance of such a provider can be registered as a Spring bean and will be consulted by the {@link Neo4jMappingContext}
|
||||
* prior to creating and populating {@link Neo4jPersistentProperty persistent properties}.
|
||||
*
|
||||
* @author Michael J. Simons
|
||||
* @soundtrack Metallica - Kill 'Em All
|
||||
* @since 6.3.7
|
||||
*/
|
||||
@API(status = STABLE, since = "6.3.7")
|
||||
public interface PersistentPropertyCharacteristicsProvider extends BiFunction<Property, Neo4jPersistentEntity<?>, PersistentPropertyCharacteristics> {
|
||||
}
|
||||
@@ -634,6 +634,37 @@ class Neo4jMappingContextTest {
|
||||
assertThat(children).containsExactly("B2", "B2a", "B3", "B3a");
|
||||
}
|
||||
|
||||
@Test
|
||||
void characteristicsShouldBeApplied() {
|
||||
|
||||
Neo4jMappingContext neo4jMappingContext1 = Neo4jMappingContext.builder().withPersistentPropertyCharacteristicsProvider((property, owner) -> {
|
||||
if (owner.getUnderlyingClass().equals(UserNode.class)) {
|
||||
if (property.getName().equals("name")) {
|
||||
return PersistentPropertyCharacteristics.treatAsTransient();
|
||||
} else if (property.getName().equals("first_name")) {
|
||||
return PersistentPropertyCharacteristics.treatAsReadOnly();
|
||||
}
|
||||
}
|
||||
if (property.getType().equals(ConvertibleType.class)) {
|
||||
return PersistentPropertyCharacteristics.treatAsTransient();
|
||||
}
|
||||
|
||||
return PersistentPropertyCharacteristics.useDefaults();
|
||||
}).build();
|
||||
Neo4jMappingContext neo4jMappingContext2 = Neo4jMappingContext.builder().build();
|
||||
|
||||
Neo4jPersistentEntity<?> userEntity = neo4jMappingContext1.getPersistentEntity(UserNode.class);
|
||||
assertThat(userEntity.getPersistentProperty("name")).isNull(); // Transient properties won't materialize
|
||||
assertThat(userEntity.getRequiredPersistentProperty("first_name").isTransient()).isFalse();
|
||||
assertThat(userEntity.getRequiredPersistentProperty("first_name").isReadOnly()).isTrue();
|
||||
|
||||
Neo4jPersistentEntity<?> entityWithConvertible = neo4jMappingContext1.getPersistentEntity(EntityWithConvertibleProperty.class);
|
||||
assertThat(entityWithConvertible.getPersistentProperty("convertibleType")).isNull();
|
||||
|
||||
entityWithConvertible = neo4jMappingContext2.getPersistentEntity(EntityWithConvertibleProperty.class);
|
||||
assertThat(entityWithConvertible.getPersistentProperty("convertibleType")).isNotNull();
|
||||
}
|
||||
|
||||
@Test // GH-2574
|
||||
void hierarchyMustBeConsistentlyReported() throws ClassNotFoundException {
|
||||
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2011-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.integration.issues.gh2640;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.neo4j.driver.Driver;
|
||||
import org.neo4j.driver.Record;
|
||||
import org.neo4j.driver.Session;
|
||||
import org.neo4j.driver.Values;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.neo4j.core.DatabaseSelectionProvider;
|
||||
import org.springframework.data.neo4j.core.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.core.mapping.PersistentPropertyCharacteristics;
|
||||
import org.springframework.data.neo4j.core.mapping.PersistentPropertyCharacteristicsProvider;
|
||||
import org.springframework.data.neo4j.core.schema.GeneratedValue;
|
||||
import org.springframework.data.neo4j.core.schema.Id;
|
||||
import org.springframework.data.neo4j.core.schema.Node;
|
||||
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager;
|
||||
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
|
||||
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
|
||||
import org.springframework.data.neo4j.test.BookmarkCapture;
|
||||
import org.springframework.data.neo4j.test.Neo4jExtension;
|
||||
import org.springframework.data.neo4j.test.Neo4jImperativeTestConfiguration;
|
||||
import org.springframework.data.neo4j.test.Neo4jIntegrationTest;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* @author Michael J. Simons
|
||||
*/
|
||||
@Neo4jIntegrationTest
|
||||
class PersistentPropertyCharacteristicsIT {
|
||||
|
||||
protected static Neo4jExtension.Neo4jConnectionSupport neo4jConnectionSupport;
|
||||
|
||||
@BeforeEach
|
||||
void setupData(@Autowired Driver driver, @Autowired BookmarkCapture bookmarkCapture) {
|
||||
|
||||
try (Session session = driver.session()) {
|
||||
session.run("MATCH (n) DETACH DELETE n").consume();
|
||||
bookmarkCapture.seedWith(session.lastBookmark());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
// GH-2640
|
||||
void implicitTransientPropertiesShouldNotBeWritten(@Autowired Driver driver, @Autowired BookmarkCapture bookmarkCapture, @Autowired Neo4jTemplate template) {
|
||||
|
||||
SomeWithImplicitTransientProperties1 node1 = template.save(new SomeWithImplicitTransientProperties1("the name", 1.23));
|
||||
SomeWithImplicitTransientProperties2 node2 = template.save(new SomeWithImplicitTransientProperties2(47.11));
|
||||
|
||||
try (Session session = driver.session(bookmarkCapture.createSessionConfig())) {
|
||||
List<Record> records = session.run("MATCH (n) WHERE n.id IN $ids RETURN n", Values.parameters("ids", Arrays.asList(node1.id.toString(), node2.id.toString()))).list();
|
||||
assertThat(records)
|
||||
.hasSize(2)
|
||||
.noneMatch(r -> {
|
||||
Map<String, Object> properties = r.get("n").asNode().asMap();
|
||||
return properties.containsKey("foobar") || properties.containsKey("bazbar");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Node
|
||||
static class SomeWithImplicitTransientProperties1 {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private UUID id;
|
||||
|
||||
private String name;
|
||||
|
||||
private Double foobar;
|
||||
|
||||
SomeWithImplicitTransientProperties1(String name, Double foobar) {
|
||||
this.name = name;
|
||||
this.foobar = foobar;
|
||||
}
|
||||
}
|
||||
|
||||
@Node
|
||||
static class SomeWithImplicitTransientProperties2 {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private UUID id;
|
||||
|
||||
private Double bazbar;
|
||||
|
||||
SomeWithImplicitTransientProperties2(Double bazbar) {
|
||||
this.bazbar = bazbar;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@EnableNeo4jRepositories(considerNestedRepositories = true)
|
||||
static class Config extends Neo4jImperativeTestConfiguration {
|
||||
|
||||
@Bean
|
||||
public BookmarkCapture bookmarkCapture() {
|
||||
return new BookmarkCapture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformTransactionManager transactionManager(
|
||||
Driver driver, DatabaseSelectionProvider databaseNameProvider) {
|
||||
|
||||
BookmarkCapture bookmarkCapture = bookmarkCapture();
|
||||
return new Neo4jTransactionManager(driver, databaseNameProvider,
|
||||
Neo4jBookmarkManager.create(bookmarkCapture));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider() {
|
||||
return (property, owner) -> {
|
||||
|
||||
if (property.getType().equals(Double.class)) {
|
||||
return PersistentPropertyCharacteristics.treatAsTransient();
|
||||
}
|
||||
|
||||
return PersistentPropertyCharacteristics.useDefaults();
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Driver driver() {
|
||||
|
||||
return neo4jConnectionSupport.getDriver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCypher5Compatible() {
|
||||
return neo4jConnectionSupport.isCypher5SyntaxCompatible();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ class Neo4jNestedMapEntityWriterTest {
|
||||
|
||||
Neo4jNestedMapEntityWriterTest() {
|
||||
|
||||
this.mappingContext = new Neo4jMappingContext(new Neo4jConversions(), InternalTypeSystem.TYPE_SYSTEM);
|
||||
this.mappingContext = Neo4jMappingContext.builder().withNeo4jConversions(new Neo4jConversions()).build();
|
||||
this.mappingContext.setInitialEntitySet(new HashSet<>(
|
||||
Arrays.asList(
|
||||
FlatEntity.class,
|
||||
|
||||
Reference in New Issue
Block a user