DATAGRAPH-1422 - Fix anchors in documentation.

This commit is contained in:
Gerrit Meier
2020-11-05 12:25:22 +01:00
parent 65997414fe
commit 9b187b60c3
15 changed files with 99 additions and 13 deletions

View File

@@ -1,3 +1,4 @@
[[coding-rules]]
= Coding Rules
The following rules are checked during a build:
@@ -8,16 +9,19 @@ The following rules are checked during a build:
- <<naming:Default>>
- <<structure:Default>>
[[coding-rules.api]]
== API
Ensure that we publish our API in a sane and consistent way.
include::api.adoc[]
[[coding-rules.naming]]
== Naming things
include::naming.adoc[]
[[coding-rules.structure]]
== Structuring things
include::structure.adoc[]

View File

@@ -1,6 +1,7 @@
[[building-SDN]]
= Building Spring Data Neo4j
[[building-SDN.requirements]]
== Requirements
* JDK 8+ (Can be https://openjdk.java.net[OpenJDK] or https://www.oracle.com/technetwork/java/index.html[Oracle JDK])
@@ -9,6 +10,7 @@
** running locally
** or indirectly via https://www.testcontainers.org[Testcontainers] and https://www.docker.com[Docker]
[[building-SDN.jdk.version]]
=== About the JDK version
Choosing JDK 8 is a decision influenced by various aspects
@@ -18,6 +20,7 @@ Spring Data commons baseline is still JDK 8 and so is Spring Framework's baselin
Thus, it is only natural to keep the JDK 8 baseline.
* While there is an increase of projects started with JDK 11 (which is Oracle's current LTS release of Java), many existing projects are still on JDK 8. We don't want to lose them as users right from the start.
[[building-SDN.running-the-build]]
== Running the build
The following sections are alternatives and roughly sorted by increased effort.
@@ -44,8 +47,10 @@ Java(TM) SE Runtime Environment (build 12.0.1+12)
Java HotSpot(TM) 64-Bit Server VM (build 12.0.1+12, mixed mode, sharing)
----
[[building-SDN.docker]]
=== With Docker installed
[[building-SDN.docker.default-image]]
==== Using the default image
If you don't have https://en.wikipedia.org/wiki/Docker_(software)[Docker] installed, head over to https://www.docker.com/products/docker-desktop[Docker Desktop].
@@ -71,6 +76,7 @@ $ mvnw.cmd clean verify
The output should be similar.
[[building-SDN.docker.another-image]]
==== Using another image
The image version to use can be configured through an environmental variable like this:
@@ -86,6 +92,7 @@ Here we are using 3.5.11 enterprise and also accept the license agreement.
Consult your operating system or shell manual on how to define environment variables if specifying them inline does not work for you.
[[building-SDN.local-database]]
=== Against a locally running database
WARNING: Running against a locally running database *will* erase its complete content.
@@ -107,6 +114,7 @@ After that, you can run a complete build by specifying the local `bolt` URL:
$ SDN_NEO4J_URL=bolt://localhost:7687 SDN_NEO4J_PASSWORD=secret ./mvnw clean verify
----
[[building-SDN.environment-variables]]
== Summary of environment variables controlling the build
[cols="3,1,3",options="header"]
@@ -136,6 +144,7 @@ We use this a lot during development.
NOTE: You need to set both `SDN_NEO4J_URL` and `SDN_NEO4J_PASSWORD` to use a local instance.
[[building-SDN.checkstyle-and-co]]
== Checkstyle and friends
There is no quality gate in place at the moment to ensure that the code/test ratio stays as is, but please consider adding tests to your contributions.
@@ -143,6 +152,7 @@ There is no quality gate in place at the moment to ensure that the code/test rat
We have some rather mild checkstyle rules in place, enforcing more or less default Java formatting rules.
Your build will break on formatting errors or something like unused imports.
[[building-SDN.jqassistant]]
=== jQAssistant
We also use https://jqassistant.org[jQAssistant], a Neo4j-based tool, to verify some aspects of our architecture.
@@ -150,6 +160,7 @@ The rules are described with Cypher and your build will break when they are viol
include::../../../../etc/jqassistant/index.adoc[leveloffset=4]
[[building-SDN.jqassistant.database]]
==== Accessing the jQAssistant database
jQAssistant uses Neo4j to store information about a project.

View File

@@ -175,8 +175,10 @@ If you require the time zone, use a type that supports it (i.e. `ZoneDateTime`)
|===
[[custom.conversions]]
== Custom conversions
[[custom.conversions.attribute.types]]
=== 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.
@@ -202,6 +204,7 @@ include::../../../../src/test/java/org/springframework/data/neo4j/documentation/
If you need multiple converters in your application, you can add as many as you need in the `Neo4jConversions` constructor.
[[custom.conversions.attribute.specific]]
=== For specific attributes only
If you need conversions only for some specific attributes, we provide `@ConvertWith`.
@@ -211,7 +214,7 @@ With an implementation of `Neo4jPersistentPropertyConverter` all specific conver
We provide `@DateLong` and `@DateString` as meta-annotated annotations for backward compatibility with Neo4j-OGM schemes not using native types.
[[composite-properties]]
[[custom.conversions.composite-properties]]
==== Composite properties
With `@CompositeProperty`, attributes of type `Map<String, Object>` or `Map<? extends Enum, Object>` can be stored as composite properties.
@@ -219,4 +222,4 @@ All entries inside the map will be added as properties to the node or relationsh
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.
be decomposed to and composed back from a map.

View File

@@ -1,6 +1,7 @@
[[Migrating]]
= Migrating from SDN+OGM to SDN
[[migrating.known-issues]]
== Known issues with past SDN+OGM migrations
SDN+OGM has had quite a history over the years and we understand that migrating big application systems is neither fun nor something that provides immediate profit.
@@ -29,12 +30,14 @@ TIP: Backed by those observations, we recommend to make sure you're using only t
Thus, your application and the access layer of your application is to large extend independent from the databases version.
From that state, consider moving from SDN+OGM to SDN.
[[migrating.preparation]]
== Prepare the migration from SDN+OGM Lovelace or SDN+OGM Moore to SDN
NOTE: The _Lovelace_ release train corresponds to SDN 5.1.x and OGM 3.1.x, while the _Moore_ is SDN 5.2.x and OGM 3.2.x.
First, you must make sure that your application runs against Neo4j in server mode over the Bolt protocol, which means work in two of three cases:
[[migrating.embedded]]
=== You're on embedded
You have added `org.neo4j:neo4j-ogm-embedded-driver` and `org.neo4j:neo4j` to you project and starting the database via OGM facilities.
@@ -46,16 +49,19 @@ Migrating from the embedded solution is probably the toughest migration, as you
It is however the one that gives you much value in itself:
In the future, you will be able to upgrade the database itself without having to consider your application framework, and your data access framework as well.
[[migrating.http]]
=== You're using the HTTP transport
You have added `org.neo4j:neo4j-ogm-http-driver` and configured an url like `http://user:password@localhost:7474`.
The dependency has to be replaced with `org.neo4j:neo4j-ogm-bolt-driver` and you need to configure a Bolt url like `bolt://localhost:7687` or use the new `neo4j://` scheme, which takes care of routing, too.
[[migrating.bolt]]
=== You're already using Bolt indirectly
A default SDN+OGM project uses `org.neo4j:neo4j-ogm-bolt-driver` and thus indirectly, the pure Java Driver.
You can keep your existing URL.
[[migrating.migrating]]
== Migrating
Once you have made sure, that your SDN+OGM application works over Bolt as expected, you can start migrating to SDN.
@@ -123,6 +129,7 @@ You're then ready to replace annotations:
NOTE: Several Neo4j-OGM annotations have not yet a corresponding annotation in SDN, some will never have.
We will add to the list above as we support additional features.
[[migrating.bookmarks]]
=== Bookmarkmanagement
Both `@EnableBookmarkManagement` and `@UseBookmark` as well as the `org.springframework.data.neo4j.bookmark.BookmarkManager`

View File

@@ -26,6 +26,7 @@ The Neo4j Client comes in two flavors:
While both versions provide an API using the same vocabulary and syntax, they are not API compatible.
Both versions feature the same, fluent API to specify queries, bind parameters and extract results.
[[neo4j-client.imperative.reactive]]
== Imperative or reactive?
Interactions with a Neo4j Client usually ends with a call to
@@ -41,6 +42,7 @@ The reactive version will in contrast return a publisher of the requested type.
Interaction with the database and retrieval of the results will not happen until the publisher is subscribed to.
The publisher can only be subscribed once.
[[neo4j-client.instance]]
== Getting an instance of the client
As with most things in SDN, both clients depend on a configured driver instance.
@@ -97,6 +99,7 @@ The client won't be able to synchronize transactions if you use another instance
Our Spring Boot starter provide a ready to use bean of the Neo4j Client that fits the environment (imperative or reactive) and you usually don't have to configure your own instance.
[[neo4j-client.usage]]
== Usage
[[neo4j-client-selecting-the-target-database]]
@@ -118,13 +121,14 @@ Flux<Map<String, Object>> allActors = client
----
<.> Select the target database in which the query is to be executed.
[[neo4j-client.specifying.queryies]]
=== Specifying queries
The interaction with the clients starts with a query.
A query can be defined by a plain `String` or a `Supplier<String>`.
The supplier will be evaluated as late as possible and can be provided by any query builder.
[[neo4j-client-specifying-queries]]
[[neo4j-client-specifying-queries.example]]
[source,java]
.Specifying a query
----
@@ -134,6 +138,7 @@ Mono<Map<String, Object>> firstActor = client
.first();
----
[[neo4j-client.retrieving.results]]
=== Retrieving results
As the previous listings shows, the interaction with the client always ends with a call to `fetch` and how many results shall be received.
@@ -178,6 +183,7 @@ System.out.println(counters.nodesDeleted() + " nodes have been deleted")
----
<.> Here the query is immediately triggered.
[[neo4j-client.mapping.parameters]]
=== Mapping parameters
Queries can contain named parameters (`$someName`) and the Neo4j client makes it easy to bind values to them.
@@ -284,6 +290,7 @@ Mono<ResultSummary> summary = client
----
<.> The `with` method allows for specifying the binder function.
[[neo4j-client.result-objects]]
=== Working with result objects
Both clients return collections or publishers of maps (`Map<String, Object>`).
@@ -310,6 +317,7 @@ Mono<Director> lily = client
`TypeSystem` gives access to the types the underlying Java driver used to fill the record.
[[neo4j-client.interacting.driver.directly]]
=== Interacting directly with the driver while using managed transactions
In case you don't want or don't like the opinionated "client" approach of the `Neo4jClient` or the `ReactiveNeo4jClient`, you can have the client delegate all interactions with the database to your code.

View File

@@ -12,6 +12,7 @@
This chapter is about the technical creation of queries when using SDN's abstraction layers.
There will be some simplifications because we do not discuss every possible case but stick with the general idea behind it.
[[query-creation.save]]
== Save
Beside the `find/load` operations the `save` operation is one of the most used when working with data.
@@ -41,6 +42,7 @@ A save operation call in general issues multiple statements against the database
WARNING: As you can see SDN does its best to keep your graph model in sync with the Java world.
This is one of the reasons why we really advise you to not load, manipulate and save sub-graphs as this might cause relationships to get removed from the database.
[[query-creation.save.multiple-entities]]
=== Multiple entities
The `save` operation is overloaded with the functionality for accepting multiple entities of the same type.
@@ -54,6 +56,7 @@ and the parameters look like
`:params {{neo4jEntities}: [{{neo4jId}: 'aa', {neo4jProperties}: {name: "PersonName", theId: "aa"}}, {{neo4jId} 'bb', {neo4jProperties}: {name: "AnotherPersonName", theId: "bb"}}]}`
[[query-creation.load]]
== Load
The `load` documentation will not only show you how the _MATCH_ part of the query looks like but also how the data gets returned.

View File

@@ -11,6 +11,7 @@ Bear in mind that SDN will not create the databases for you.
You can do this with the help of a https://github.com/michael-simons/neo4j-migrations[migrations tool]
or of course with a simple script upfront.
[[faq.multidatabase.statically]]
=== Statically configured
Configure the database name to use in your Spring Boot configuration like this (the same property applies of course for YML or environment based configuration, with Spring Boot's conventions applied):
@@ -22,6 +23,7 @@ org.neo4j.data.database = yourDatabase
With that configuration in place, all queries generated by all instances of SDN repositories (both reactive and imperative) and by the `ReactiveNeo4jTemplate` respectively `Neo4jTemplate` will be executed against the database `yourDatabase`.
[[faq.multidatabase.dynamically]]
=== Dynamically configured
Provide a bean with the type `Neo4jDatabaseNameProvider` or `ReactiveDatabaseSelectionProvider` depending on the type of your Spring application.
@@ -49,12 +51,14 @@ NOTE: Be careful that you don't mix up entities retrieved from one database with
The database name is requested for each new transaction, so you might end up with less or more entities than expected when changing the database name in between calls.
Or worse, you could inevitably store the wrong entities in the wrong database.
[[faq.transactions.cluster]]
== Do I need specific configuration so that transactions work seamless with a Neo4j Causal Cluster?
No, you don't.
SDN uses Neo4j Causal Cluster bookmarks internally without any configuration on your side required.
Transactions in the same thread or the same reactive stream following each other will be able to read their previously changed values as you would expect.
[[faq.annotations.specific]]
== Do I need to use Neo4j specific annotations?
No.
@@ -80,11 +84,13 @@ You are free to use the following, equivalent Spring Data annotations:
|===
[[faq.ids.assignment]]
== How do I use assigned ids?
Just use `@Id` without `@GeneratedValue` and fill your id attribute via a constructor parameter or a setter or _wither_.
See this https://medium.com/neo4j/neo4j-ogm-and-spring-data-neo4j-a55a866df68c[blog post] for some general remarks about finding good ids.
[[faq.ids.externally]]
== How do I use externally generated ids?
We provide the interface `org.springframework.data.neo4j.core.schema.IdGenerator`.
@@ -146,6 +152,7 @@ And here is the reactive version, omitting the setup for brevity:
include::../../../../src/test/java/org/springframework/data/neo4j/documentation/spring_boot/ReactiveTemplateExampleTest.java[tags=faq.template-reactive]
----
[[faq.parameters.custom-query]]
== How do I specify parameters in custom queries?
You do this exactly the same way as in a standard Cypher query issued in the Neo4j Browser or the Cypher-Shell, with the `$` syntax (from Neo4j 4.0 on upwards, the old `{foo}` syntax for Cypher parameters has been removed from the database);
@@ -164,6 +171,7 @@ The Spring Boot Maven and Gradle plugins do this automatically for you.
If this is not feasible for any reason, you can either add
`@Param` and specify the name explicitly or use the parameters index.
[[faq.spel.custom-query]]
== How do I use Spring Expression Language in custom queries?
{spring-framework-ref}/core.html#expressions[Spring Expression Language (SpEL)] can be used in custom queries inside `:#{}`.
@@ -183,6 +191,7 @@ Don't confuse this with the above Cypher syntax!
The SpEL expression concatenates both parameters into one single value that is eventually passed on to the <<neo4j-client>>.
The SpEL block ends with `}`.
[[faq.entities.auditing]]
== How do I audit entities?
All Spring Data annotations are supported.
@@ -193,6 +202,7 @@ Those are
* `org.springframework.data.annotation.LastModifiedBy`
* `org.springframework.data.annotation.LastModifiedDate`
[[faq.find-by-example]]
== How do I use "Find by example"?
"Find by example" is a new feature in SDN.
@@ -219,6 +229,7 @@ movieExample = Example.of(
movies = this.movieRepository.findAll(movieExample);
----
[[faq.spring-boot.sdn]]
== Do I need Spring Boot to use Spring Data Neo4j?
No, you don't.
@@ -240,6 +251,7 @@ The coordinates for a Gradle setup are the same.
To select a different database - either statically or dynamically - you can add a Bean of type `DatabaseSelectionProvider` as explained in <<faq.multidatabase>>.
For a reactive scenario, we provide `ReactiveDatabaseSelectionProvider`.
[[faq.sdn-without-spring-boot]]
=== Using Spring Data Neo4j inside a Spring context without Spring Boot
We provide two abstract configuration classes to support you in bringing in the necessary beans: `AbstractNeo4jConfig` for imperative database access and `AbstractReactiveNeo4jConfig` for the reactive version.
@@ -321,6 +333,7 @@ class MyConfiguration extends AbstractReactiveNeo4jConfig {
}
----
[[faq.sdn-in-cdi-2.0]]
=== Using Spring Data Neo4j in a CDI 2.0 environment
For your convenience we provide a CDI extension with `Neo4jCdiExtension`.
@@ -385,4 +398,4 @@ public class SomeClass {
}
}
}
----
----

View File

@@ -15,6 +15,7 @@ SDN supports
Those are all included in the same binary.
The reactive programming model requires a 4.0 Neo4j server on the database side and reactive Spring on the other hand.
[[prepare-the-database]]
== Prepare the database
For this example, we stay within the https://neo4j.com/developer/movie-database/[movie graph], as it comes for free with every Neo4j instance.
@@ -33,6 +34,7 @@ The above command sets the password of the server to `secret`.
Note the command ready to run in the prompt (`:play movies`).
Execute it to fill your database with some test data.
[[create-spring-boot-project]]
== Create a new Spring Boot project
The easiest way to setup a Spring Boot project is https://start.spring.io[start.spring.io]
@@ -41,6 +43,7 @@ The easiest way to setup a Spring Boot project is https://start.spring.io[start.
Select the "Spring Web Starter" to get all the dependencies needed for creating a Spring based web application.
The Spring Initializr will take care of creating a valid project structure for you, with all the files and settings in place for the selected build tool.
[[create-spring-boot-project-using-maven]]
=== Using Maven
You can issue a _curl_ request against the Spring Initializer to create a basic Maven project:
@@ -71,6 +74,7 @@ As this starter is not yet on the initializer, you will have to add the followin
You would also add the dependency manually in case of an existing project.
[[create-spring-boot-project-using-gradle]]
=== Using Gradle
The idea is the same, just generate a Gradle project:
@@ -99,6 +103,7 @@ dependencies {
You would also add the dependency manually in case of an existing project.
[[configure-spring-boot-project]]
== Configure the project
Now open any of those projects in your favorite IDE.
@@ -106,9 +111,9 @@ Find `application.properties` and configure your Neo4j credentials:
[source,properties]
----
org.neo4j.driver.uri=bolt://localhost:7687
org.neo4j.driver.authentication.username=neo4j
org.neo4j.driver.authentication.password=secret
spring.neo4j.uri=bolt://localhost:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret
----
This is the bare minimum of what you need to connect to a Neo4j instance.
@@ -116,6 +121,7 @@ This is the bare minimum of what you need to connect to a Neo4j instance.
NOTE: It is not necessary to add any programmatic configuration of the driver when you use this starter.
SDN repositories will be automatically enabled by this starter.
[[create-domain-spring-boot-project]]
== Create your domain
Our domain layer should accomplish two things:
@@ -123,6 +129,7 @@ Our domain layer should accomplish two things:
* Map your graph to objects
* Provide access to those
[[example-node-spring-boot-project]]
=== Example Node-Entity
SDN fully supports unmodifiable entities, for both Java and `data` classes in Kotlin.
@@ -200,6 +207,7 @@ It creates a new entity and sets the field accordingly, without modifying the or
You can of course use SDN with https://kotlinlang.org/[Kotlin] and model your domain with Kotlin's data classes.
https://projectlombok.org/[Project Lombok] is an alternative if you want or need to stay purely within Java.
[[spring-data-repositories-spring-boot-project]]
=== Declaring Spring Data repositories
You basically have two options here:

View File

@@ -51,7 +51,7 @@ include::object-mapping/index.adoc[]
include::{spring-data-commons-docs}/repository-projections.adoc[leveloffset=+1]
include::object-mapping/projections.adoc[leveloffset=+1,lines=5..]
include::object-mapping/projections.adoc[leveloffset=+1,lines=4..]
include::testing/index.adoc[]

View File

@@ -74,6 +74,7 @@ Find some more information about it in <<template-support,our FAQ>>.
The Neo4j Client as such is unique to SDN.
You will find it's documentation in the <<neo4j-client,appendix>>.
[[sdn-packages]]
== On the package level
[%header,cols=2*]

View File

@@ -60,6 +60,7 @@ JVM primitives are mapped to node or relationship properties.
An OGM abstracts the database and provides a convenient way to persist your domain model in the graph and query it without having to use low level drivers directly.
It also provides the flexibility to the developer to supply custom queries where the queries generated by SDN are insufficient.
[[what-is-in-the-box-sdn]]
=== What's in the box?
Spring Data Neo4j or in short SDN is a next-generation https://spring.io/projects/spring-data[Spring Data] module, created and maintained by https://neo4j.com[Neo4j, Inc.] in close collaboration with https://www.vmware.com/[VMware's] Spring Data Team.
@@ -73,6 +74,7 @@ Noteworthy features that differentiate the new SDN from Spring Data Neo4j + OGM
* Full support for the reactive programming model in the Spring Framework itself and Spring Data
* Brand new Neo4j client and reactive client feature, resurrecting the idea of a template over the plain driver, easing database access
[[why-should-you-favor-sdn]]
=== Why should I use SDN in favor of SDN+OGM
SDN has several features not present in SDN+OGM, notably
@@ -82,6 +84,7 @@ SDN has several features not present in SDN+OGM, notably
* Full support for fully immutable entities
* Support for all modifiers and variations of derived finder methods, including spatial queries
[[sdn-related-to-ogm]]
=== How does SDN relate to Neo4j-OGM?
https://neo4j.com/docs/ogm-manual/current/[Neo4j-OGM] is an Object Graph Mapping library, which is mainly used by previous versions of Spring Data Neo4j as its backend for the heavy lifting of mapping nodes and relationships into domain object.
@@ -90,18 +93,22 @@ SDN uses Spring Data's mapping context exclusively for scanning classes and buil
While this pins SDN to the Spring ecosystem, it has several advantages, among them the smaller footprint regarding CPU and memory usage and especially, all the features of Spring's mapping context.
[[sdn-and-http-support]]
=== Does SDN support connections over HTTP to Neo4j?
No.
[[sdn-and-embedded-support]]
=== Does SDN support embedded Neo4j?
Embedded Neo4j has multiple facets to it:
[[sdn-and-embedded-instances-support]]
==== Does SDN provide an embedded instance for your application?
No.
[[sdn-interact-with-embedded-instances]]
==== Does SDN interact directly with an embedded instance?
No.
@@ -111,6 +118,7 @@ SDN can however work very much with Neo4j's test harness, the test harness is sp
Support for both Neo4j 3.5 and 4.0 test harness is implemented via link:{java-driver-starter-href}[the Spring Boot starter for the driver].
Have a look at the corresponding module `org.neo4j.driver:neo4j-java-driver-test-harness-spring-boot-autoconfigure`.
[[sdn-without-spring-boot]]
==== Can I use SDN without Spring Boot?
Yes, see our `README`.

View File

@@ -14,9 +14,11 @@ To take full advantage of the object mapping functionality inside SDN, you shoul
Although it is not necessary for the mapping framework to have this annotation (your POJOs are mapped correctly, even without any annotations), it lets the classpath scanner find and pre-process your domain objects to extract the necessary metadata.
If you do not use this annotation, your application takes a slight performance hit the first time you store a domain object, because the mapping framework needs to build up its internal metadata model so that it knows about the properties of your domain object and how to persist them.
[[mapping.annotations.overview]]
=== Mapping Annotation Overview
==== From SDN:
[[mapping.annotations.overview.from.sdn]]
==== From SDN
* `@Node`: Applied at the class level to indicate this class is a candidate for mapping to the database.
* `@Id`: Applied at the field level to mark the field used for identity purpose.
@@ -36,6 +38,7 @@ The following annotations are used to specify conversions and ensure backwards c
See <<conversions>> for more information on that.
[[mapping.annotations.overview.from.commons]]
==== From Spring Data commons
* `@org.springframework.data.annotation.Id` same as `@Id` from SDN, in fact, `@Id` is annotated with Spring Data Common's Id-annotation.
@@ -50,6 +53,7 @@ The initial value is zero which is bumped automatically on every update.
Have a look at <<auditing>> for all annotations regarding auditing support.
[[mapping.annotations.node]]
=== The basic building block: `@Node`
The `@Node` annotation is used to mark a class as a managed domain class, subject to the classpath scanning by the mapping context.
@@ -76,6 +80,7 @@ This allows polymorphic queries: You can pass in base or intermediate classes an
This is only supported for abstract bases annotated with `@Node`.
The labels defined on such a class will be used as additional labels together with the labels of the concrete implementations.
[[mapping.annotations.node.dynamic.labels]]
==== Dynamic or "runtime" managed labels
All labels implicitly defined through the simple class name or explicitly via the `@Node` annotation are static.
@@ -89,6 +94,7 @@ During writes, all labels of the node will be replaced with the statically defin
WARNING: If you have other applications add additional labels to nodes, don't use `@DynamicLabels`.
If `@DynamicLabels` is present on a managed entity, the resulting set of labels will be "the truth" written to the database.
[[mapping.annotations.id]]
=== Identifying instances: `@Id`
While `@Node` creates a mapping between a class and nodes having a specific label, we also need to make the connection between individual instances of that class (objects) and instances of the node.
@@ -116,6 +122,7 @@ That bean also needs to implement `IdGenerator`, but can make use of everything
NOTE: Don't skip the important notes about ID handling in <<mapping.id-handling>>
[[mapping.annotations.property]]
=== Mapping properties: `@Property`
All attributes of a `@Node`-annotated class will be persisted as properties of Neo4j nodes and relationships.
@@ -124,6 +131,7 @@ Without further configuration, the name of the attribute in the Java or Kotlin c
If you are working with an existing Neo4j schema or just like to adapt the mapping to your needs, you will need to use `@Property`.
The `name` is used to specify the name of the property inside the database.
[[mapping.annotations.relationship]]
=== Connecting nodes: `@Relationship`
The `@Relationship` annotation can be used on all attributes that are not a simple type.
@@ -136,6 +144,7 @@ We support dynamic relationships.
Dynamic relationships are represented as a `Map<String, AnnotatedDomainClass>` or `Map<Enum, AnnotatedDomainClass>`.
In such a case, the type of the relationship to the other domain class is given by the maps key and must not be configured through the `@Relationship`.
[[mapping.annotations.relationship.properties]]
==== Map relationship properties
Neo4j supports defining properties not only on nodes but also on relationships.
@@ -157,6 +166,7 @@ include::../../../../src/test/java/org/springframework/data/neo4j/documentation/
include::../../../../src/test/java/org/springframework/data/neo4j/documentation/domain/MovieEntity.java[tags=mapping.relationship.properties]
----
[[mapping.annotations.relationship.remarks]]
==== Relationship query remarks
In general there is no limitation of relationships / hops for creating the queries.
@@ -170,6 +180,7 @@ This won't be problematical if the relationship from _movie_ to _actor_ were jus
In a bidirectional scenario SDN would fetch the particular _movie_, its _actors_ but also the other movies defined for this _actor_ per definition of the relationship.
In the worst case, this will cascade to fetching the whole graph for a single entity.
[[mapping.annotations.example]]
=== A complete example
Putting all those together, we can create a simple domain.
@@ -213,6 +224,7 @@ While you can do this, you may end up rebuilding a graph database inside your ob
[[mapping.id-handling]]
== Handling and provisioning of unique IDs
[[mapping.id-handling.internal-id]]
=== Using the internal Neo4j id
The easiest way to give your domain classes an unique identifier is the combination of `@Id` and `@GeneratedValue`
@@ -283,6 +295,7 @@ You either have to provide a setter for the id attribute or something like a _wi
* Disadvantage: It is tied to Neo4js internal database id, which is not unique to our application entity only over a database lifetime.
* Disadvantage: It takes more effort to create an immutable entity
[[mapping.id-handling.external-id]]
=== Use externally provided surrogate keys
The `@GeneratedValue` annotation can take a class implementing `org.springframework.data.neo4j.core.schema.IdGenerator` as parameter.
@@ -388,6 +401,7 @@ public class MovieEntity {
----
====
[[mapping.id-handling.business-key]]
=== Using a business key
We have been using a business key in the complete example's `MovieEntity` and <<mapping.complete-example.person,`PersonEntity`>>.

View File

@@ -1,7 +1,7 @@
[[projections]]
[[projections.sdn]]
= Projections
[[projections.general-remarks]]
[[projections.sdn.general-remarks]]
== General remarks
As stated above, projections come in two flavors: Interface and DTO based projections.
@@ -31,7 +31,8 @@ additional properties - via accessors or fields - Spring Data Neo4j looks in the
Properties must match exactly by name and can be of simple types (as defined in `org.springframework.data.neo4j.core.convert.Neo4jSimpleTypes`)
or of known persistent entites. Collections of those are supported, but maps are not.
=== A full example
[[projections.sdn.full-example]]
== A full example
Given the following entities, projections and the corresponding repository:

View File

@@ -204,6 +204,7 @@ Even if the intent is that the calculation should be preferred, it's important t
The core idea here is to use factory methods instead of additional constructors to avoid the need for constructor disambiguation through `@PersistenceConstructor`.
Instead, defaulting of properties is handled within the factory method.
[[mapping.fundamentals.recommendations]]
== General recommendations
* _Try to stick to immutable objects_ --
@@ -226,6 +227,7 @@ As persistence operations usually require a constructor taking all arguments, th
Spring Data adapts specifics of Kotlin to allow object creation and mutation.
[[mapping.fundamentals.kotlin.object-creation]]
=== Kotlin object creation
Kotlin classes are supported to be instantiated , all classes are immutable by default and require explicit property declarations to define mutable properties.
@@ -265,6 +267,7 @@ data class Person(var id: String, val name: String = "unknown")
Every time the `name` parameter is either not part of the result or its value is `null`, then the `name` defaults to `unknown`.
[[mapping.fundamentals.kotlin.property-population]]
=== Property population of Kotlin data classes
In Kotlin, all classes are immutable by default and require explicit property declarations to define mutable properties.

View File

@@ -1,6 +1,7 @@
[[testing]]
[[sdn.testing]]
= Testing
[[sdn.testing.without.spring-boot]]
== Without Spring Boot
We work a lot with our abstract base classes for configuration in our own integration tests. They can be used like this:
@@ -339,6 +340,7 @@ class MovieRepositoryTCTest {
}
----
[[dataneo4jtest-dynamicpropertysource-alternatives]]
=== Alternatives to a `@DynamicPropertySource`
There are some scenarios in which the above annotation does not fit your usecase.