Conversions

Convention-based Mapping

The Neo4j Converter has a few conventions for mapping objects when no additional mapping metadata is provided. The conventions are:

  • The short Java class name is mapped to the primary label in the following manner: The class com.bigbank.SavingsAccount maps to the savingsAccount primary label.

  • The converter uses any Spring Converter registered with it to override the default mapping of object properties to node fields and values.

  • The fields of an object are used to convert to and from fields in the graph. Public JavaBean properties are not used.

  • If you have a single non-zero-argument constructor whose constructor argument names match top-level property names of node, that constructor is used. Otherwise, the zero-argument constructor is used. If there is more than one non-zero-argument constructor, an exception will be thrown.

We support a broad range of conversions out of the box. Find the list of supported cypher types in the official drivers manual: Type mapping.

Primitive types of wrapper types are equally supported.

Domain type Cypher type Maps directly to native type

java.lang.Boolean

Boolean

boolean[]

List of Boolean

java.lang.Long

Integer

long[]

List of Integer

java.lang.Double

Float

double[]

List of Float

java.lang.String

String

java.lang.String[]

List of String

byte[]

ByteArray

java.lang.Byte

ByteArray with length 1

java.lang.Character

String with length 1

char[]

List of String with length 1

java.util.Date

String formatted as ISO 8601 Date (yyyy-MM-dd’T’HH:mm:ss.SSSZ). Notice the Z: SDN will store all java.util.Date instances in UTC. If you require the time zone, use a type that supports it (i.e. ZoneDateTime) or store the zone as a separate property.

java.lang.Float

String

float[]

List of String

java.lang.Integer

Integer

int[]

List of Integer

java.util.Locale

String formatted as BCP 47 language tag

java.lang.Short

Integer

short[]

List of Integer

java.math.BigDecimal

String

java.math.BigInteger

String

java.time.LocalDate

Date

java.time.OffsetTime

Time

java.time.LocalTime

LocalTime

java.time.ZonedDateTime

DateTime

java.time.LocalDateTime

LocalDateTime

java.time.OffsetDateTime

DateTime

java.time.Instant

DateTime

java.util.TimeZone

String

java.time.ZoneId

String

java.time.Period

Duration

java.time.Duration

Duration

org.neo4j.driver.types.IsoDuration

Duration

org.neo4j.driver.types.Point

Point

org.springframework.data.neo4j.types.GeographicPoint2d

Point with CRS 4326

org.springframework.data.neo4j.types.GeographicPoint3d

Point with CRS 4979

org.springframework.data.neo4j.types.CartesianPoint2d

Point with CRS 7203

org.springframework.data.neo4j.types.CartesianPoint3d

Point with CRS 9157

org.springframework.data.geo.Point

Point with CRS 4326 and x/y corresponding to lat/long

Instances of Enum

String (The name value of the enum)

Instances of Enum[]

List of String (The name value of the enum)

java.net.URL

String

java.net.URI

String

java.util.UUID

String

Custom conversions

For attributes of a given type

If you prefer to work with your own types in the entities or as parameters for @Query annotated methods, you can define and provide a custom converter implementation. First you have to implement a GenericConverter and register the types your converter should handle. For entity property type converters you need to take care of converting your type to and from a Neo4j Java Driver Value. If your converter is supposed to work only with custom query methods in the repositories, it is sufficient to provide the one-way conversion to the Value type.

Example of a custom converter implementation
public class MyCustomTypeConverter implements GenericConverter {

	@Override
	public Set<ConvertiblePair> getConvertibleTypes() {
		Set<ConvertiblePair> convertiblePairs = new HashSet<>();
		convertiblePairs.add(new ConvertiblePair(MyCustomType.class, Value.class));
		convertiblePairs.add(new ConvertiblePair(Value.class, MyCustomType.class));
		return convertiblePairs;
	}

	@Override
	public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
		if (MyCustomType.class.isAssignableFrom(sourceType.getType())) {
			// convert to Neo4j Driver Value
			return convertToNeo4jValue(source);
		} else {
			// convert to MyCustomType
			return convertToMyCustomType(source);
		}
	}

}

To make SDN aware of your converter, it has to be registered in the Neo4jConversions. To do this, you have to create a @Bean with the type org.springframework.data.neo4j.core.convert.Neo4jConversions. Otherwise, the Neo4jConversions will get created in the background with the internal default converters only.

Example of a custom converter implementation
@Bean
public Neo4jConversions neo4jConversions() {
	Set<GenericConverter> additionalConverters = Collections.singleton(new MyCustomTypeConverter());
	return new Neo4jConversions(additionalConverters);
}

If you need multiple converters in your application, you can add as many as you need in the Neo4jConversions constructor.

For specific attributes only

If you need conversions only for some specific attributes, we provide @ConvertWith. This is an annotation that can be put on attributes of both entities (@Node) and relationship properties (@RelationshipProperties) It defines a Neo4jPersistentPropertyConverter via the converter attribute and an optional Neo4jPersistentPropertyConverterFactory to construct the former. With an implementation of Neo4jPersistentPropertyConverter all specific conversions for a given type can be addressed. In addition, @ConvertWith also provides converterRef for referencing any Spring bean in the application context implementing Neo4jPersistentPropertyConverter. The referenced bean will be preferred over constructing a new converter.

We provide @DateLong and @DateString as meta-annotated annotations for backward compatibility with Neo4j-OGM schemes not using native types. Those are meta annotated annotations building on the concept above.

Composite properties

With @CompositeProperty, attributes of type Map<String, Object> or Map<? extends Enum, Object> can be stored as composite properties. All entries inside the map will be added as properties to the node or relationship containing the property. Either with a configured prefix or prefixed with the name of the property. While we only offer that feature for maps out of the box, you can Neo4jPersistentPropertyToMapConverter and configure it as the converter to use on @CompositeProperty. A Neo4jPersistentPropertyToMapConverter needs to know how a given type can be decomposed to and composed back from a map.