diff --git a/README.adoc b/README.adoc index aad59394b..ee959d94b 100644 --- a/README.adoc +++ b/README.adoc @@ -4,13 +4,14 @@ image:https://spring.io/badges/spring-data-neo4j/ga.svg[Spring Data Neo4j,link=h :sectanchors: // tag::properties[] -:neo4jGroupId: org.springframework.data.neo4j +:neo4jGroupId: org.springframework.data :artifactId: spring-data-neo4j +:groupIdStarter: org.springframework.boot :artifactIdStarter: spring-boot-starter-data-neo4j -:neo4j-version: 4.0.4 -:spring-boot-version: 2.4.0.M3 -:spring-data-neo4j-version: 6.0.0-SNAPSHOT +:neo4j-version: 4.1.3 +:spring-boot-version: 2.4.0-RC1 +:spring-data-neo4j-version: 6.0.0 // end::properties[] [abstract] @@ -32,7 +33,7 @@ Please report unacceptable behavior to spring-code-of-conduct@pivotal.io. == Manual For a gentle introduction and some getting started guides, please use our -https://neo4j.github.io/sdn-rx[Manual]. +https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#reference[Manual]. == Getting Started @@ -60,7 +61,7 @@ spring.neo4j.authentication.username=neo4j spring.neo4j.authentication.password=secret ---- -Please have a look at our https://neo4j.github.io/sdn-rx[manual] for an overview about the architecture, how to define +Please have a look at our https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#reference[manual] for an overview about the architecture, how to define mappings and more. ==== Without Spring Boot diff --git a/etc/jqassistant/api.adoc b/etc/jqassistant/api.adoc index d187b5c2d..114ecaec2 100644 --- a/etc/jqassistant/api.adoc +++ b/etc/jqassistant/api.adoc @@ -11,8 +11,8 @@ and annotations. [source,cypher,role="constraint"] .@API Guardian annotations must not be used on fields ---- -MATCH (c:Java) - [:ANNOTATED_BY] -> (a) - [:OF_TYPE] -> (t:Type {fqn: 'org.apiguardian.api.API'}), - (p) - [:DECLARES] -> (c) +MATCH (c:Java)-[:ANNOTATED_BY]->(a)-[:OF_TYPE]->(t:Type {fqn: 'org.apiguardian.api.API'}), + (p)-[:DECLARES]->(c) WHERE c:Member AND NOT c:Constructor RETURN p.fqn, c.name ---- @@ -23,8 +23,8 @@ Public interfaces, classes or annotations are either part of internal or public [source,cypher,role="concept",verify=rowCount,rowCountMin=0] .Define which Java artifacts are part of internal or public API ---- -MATCH (c:Java) - [:ANNOTATED_BY] -> (a) - [:OF_TYPE] -> (t:Type {fqn: 'org.apiguardian.api.API'}), - (a) - [:HAS] -> ({name: 'status'}) - [:IS] -> (s) +MATCH (c:Java)-[:ANNOTATED_BY]->(a)-[:OF_TYPE]->(t:Type {fqn: 'org.apiguardian.api.API'}), + (a)-[:HAS]->({name: 'status'})-[:IS]->(s) WHERE ANY (label IN labels(c) WHERE label in ['Interface', 'Class', 'Annotation']) WITH c, trim(split(s.signature, ' ')[1]) AS status WITH c, status, @@ -33,7 +33,7 @@ WITH c, status, ELSE 'Public' END AS type MERGE (a:Api {type: type, status: status}) -MERGE (c) - [:IS_PART_OF] -> (a) +MERGE (c)-[:IS_PART_OF]->(a) RETURN c,a ---- @@ -45,7 +45,7 @@ See ADR-003. [source,cypher,role="constraint",requiresConcepts="api:api-guardian-api-concept"] .Non abstract, public classes that are only part of internal API must be final ---- -MATCH (c:Class) - [:IS_PART_OF] -> (:Api {type: 'Internal'}) +MATCH (c:Class)-[:IS_PART_OF]->(:Api {type: 'Internal'}) WHERE c.visibility = 'public' AND coalesce(c.abstract, false) = false AND NOT exists(c.final) diff --git a/etc/jqassistant/structure.adoc b/etc/jqassistant/structure.adoc index 638070384..36e2052bb 100644 --- a/etc/jqassistant/structure.adoc +++ b/etc/jqassistant/structure.adoc @@ -8,9 +8,9 @@ Most of the time, the package structure under `org.springframework.data.neo4j` s .The mapping package must not depend on any other SDN packages than `schema` and `convert` ---- MATCH (a:Main:Artifact) -OPTIONAL MATCH (a) -[:CONTAINS]-> (s:Package) WHERE s.fqn in ['org.springframework.data.neo4j.core.schema', 'org.springframework.data.neo4j.core.convert'] +OPTIONAL MATCH (a)-[:CONTAINS]->(s:Package) WHERE s.fqn in ['org.springframework.data.neo4j.core.schema', 'org.springframework.data.neo4j.core.convert'] WITH collect(s) as allowed, a -MATCH (a) -[:CONTAINS]-> (p1:Package) -[:DEPENDS_ON]-> (p2:Package) <-[:CONTAINS]- (a) +MATCH (a)-[:CONTAINS]->(p1:Package)-[:DEPENDS_ON]->(p2:Package)<-[:CONTAINS]-(a) WHERE p1.fqn = 'org.springframework.data.neo4j.core.mapping' AND NOT (p2 in allowed OR (p1) -[:CONTAINS]-> (p2)) RETURN p1,p2 @@ -21,7 +21,7 @@ RETURN p1,p2 .The public support packages must not depend directly on the mapping package ---- MATCH (a:Main:Artifact) -MATCH (a) -[:CONTAINS]-> (p1:Package) +MATCH (a)-[:CONTAINS]->(p1:Package) WHERE p1.fqn in [ 'org.springframework.data.neo4j.core.convert', 'org.springframework.data.neo4j.core.schema', @@ -29,8 +29,8 @@ WHERE p1.fqn in [ 'org.springframework.data.neo4j.core.transaction' ] WITH p1, a -MATCH (p1) - [:CONTAINS] -> (t:Type) -MATCH (t) - [:DEPENDS_ON] -> (t2:Type) <- [:CONTAINS] - (p2:Package) <-[:CONTAINS]- (a) +MATCH (p1)-[:CONTAINS]->(t:Type) +MATCH (t)-[:DEPENDS_ON]->(t2:Type)<-[:CONTAINS]-(p2:Package)<-[:CONTAINS]-(a) WHERE t2.fqn <> 'org.springframework.data.neo4j.core.mapping.Neo4jPersistentProperty' AND p2.fqn = 'org.springframework.data.neo4j.core.mapping' RETURN t diff --git a/src/main/asciidoc/appendix/build.adoc b/src/main/asciidoc/appendix/build.adoc index 31a669895..2219e825b 100644 --- a/src/main/asciidoc/appendix/build.adoc +++ b/src/main/asciidoc/appendix/build.adoc @@ -14,9 +14,9 @@ Choosing JDK 8 is a decision influenced by various aspects * SDN is a Spring Data project. -Spring Data commons baseline is still JDK 8 and so is Spring Frameworks baseline. -Thus it is only natural to keep the JDK 8 baseline. -* While there is an increase of projects started with JDK 11 (which is Oracles 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. +Spring Data commons baseline is still JDK 8 and so is Spring Framework's baseline. +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. == Running the build @@ -49,7 +49,7 @@ Java HotSpot(TM) 64-Bit Server VM (build 12.0.1+12, mixed mode, sharing) ==== 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]. -In short, Docker is a tool that helps you running lightweight software images using OS-level virtualization in so called containers. +In short, Docker is a tool that helps you running lightweight software images using OS-level virtualization in so-called containers. Our build uses https://www.testcontainers.org/modules/databases/neo4j/[Testcontainers Neo4j] to bring up a database instance. @@ -71,9 +71,6 @@ $ mvnw.cmd clean verify The output should be similar. -At the moment, this build tests against Neo4j 3.5, as 4.0 is not yet available on Docker Hub. -As a consequence, tests requiring a reactive capable database, are skipped, as this is a feature of Neo4j 4.0. - ==== Using another image The image version to use can be configured through an environmental variable like this: @@ -97,7 +94,6 @@ Building against a locally running database is faster, as it does not restart a We do this a lot during our development. You can get a copy of Neo4j at our https://neo4j.com/download-center/#enterprise[download center] free of charge. -Especially you can get https://neo4j.com/download-center/?ref=blog/#prerelease[the current prelease of Neo4j 4.0], supporting all the reactive features. Please download the version applicable to your operating system and follow the instructions to start it. A required step is to open a browser and go to http://localhost:7474 after you started the database and change the default password from `neo4j` to something of your liking. diff --git a/src/main/asciidoc/appendix/conversions.adoc b/src/main/asciidoc/appendix/conversions.adoc index 8ba2587ae..9202893a8 100644 --- a/src/main/asciidoc/appendix/conversions.adoc +++ b/src/main/asciidoc/appendix/conversions.adoc @@ -205,7 +205,7 @@ If you need multiple converters in your application, you can add as many as you === 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 carrying a `Neo4jPersistentPropertyConverter` on it's `converter` attribute +This is an annotation that can be put on attributes carrying a `Neo4jPersistentPropertyConverter` on its `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. @@ -214,7 +214,7 @@ We provide `@DateLong` and `@DateString` as meta-annotated annotations for backw [[composite-properties]] ==== Composite properties -With `@CompositeProperty`, attributes of type `Map` or Map` can be stored as composite properties. +With `@CompositeProperty`, attributes of type `Map` or `Map` 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 diff --git a/src/main/asciidoc/appendix/migrating.adoc b/src/main/asciidoc/appendix/migrating.adoc index 8e9753cee..98a9c5f5d 100644 --- a/src/main/asciidoc/appendix/migrating.adoc +++ b/src/main/asciidoc/appendix/migrating.adoc @@ -10,7 +10,7 @@ Having skipped more than one major upgrade:: While Neo4j-OGM can be used stand-alone, Spring Data Neo4j cannot. It depends to large extend on the Spring Data and therefore, on the Spring Framework itself, which eventually affects large parts of your application. Depending on how the application has been structured, that is, how much the any of the framework part leaked into your business code, the more you have to adapt your application. -It get's worse when you have more than one Spring Data module in your application, if you accessed a relational database in the same service layer as your graph database. +It gets worse when you have more than one Spring Data module in your application, if you accessed a relational database in the same service layer as your graph database. Updating two object mapping frameworks is not fun. Relying on a embedded database configured through Spring Data itself:: The embedded database in a SDN+OGM project is configured by Neo4j-OGM. @@ -23,7 +23,7 @@ Spring Data however depends on Spring Framework and than the arguments from the Being unsure about which building blocks to include:: It's not easy to get the terms right. We wrote the building blocks of an SDN+OGM setting https://michael-simons.github.io/neo4j-sdn-ogm-tips/what_are_the_building_blocks_of_sdn_and_ogm.html[here]. -It may be so that all of them have been added by coincidence and you're dealing with a lof of conflicting dependencies. +It may be so that all of them have been added by coincidence and you're dealing with a lot of conflicting dependencies. TIP: Backed by those observations, we recommend to make sure you're using only the Bolt or http transport in your current application before switching from SDN+OGM to SDN. Thus, your application and the access layer of your application is to large extend independent from the databases version. @@ -38,11 +38,11 @@ First, you must make sure that your application runs against Neo4j in server mod === 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. -This is no longer supported and you have to setup a standard Neo4j server (both standalone and cluster are supported). +This is no longer supported and you have to set up a standard Neo4j server (both standalone and cluster are supported). The above dependencies have to be removed. -Migrating from the embedded solution is probably the toughest migration, as you need to setup a server, too. +Migrating from the embedded solution is probably the toughest migration, as you need to set up a server, too. 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. @@ -74,7 +74,7 @@ With our starter in place, all the necessary bits apart from the connection URL .Old and new properties compared ---- # Old -spring.data.neo4j.embedded.enabled=false # No longer support +spring.data.neo4j.embedded.enabled=false # No longer supported spring.data.neo4j.uri=bolt://localhost:7687 spring.data.neo4j.username=neo4j spring.data.neo4j.password=secret @@ -85,11 +85,11 @@ spring.neo4j.authentication.username=neo4j spring.neo4j.authentication.password=secret ---- -WARNING: Those new properties might change in the future again when SDN and the driver will eventually replace the old setup fully. +WARNING: Those new properties might change in the future again when SDN and the driver eventually fully replace the old setup. And finally, add the new dependency, see <> for both Gradle and Maven. -You're than ready to replace annotations: +You're then ready to replace annotations: [cols="2*",options="header"] |=== @@ -126,7 +126,7 @@ We will add to the list above as we support additional features. === Bookmarkmanagement Both `@EnableBookmarkManagement` and `@UseBookmark` as well as the `org.springframework.data.neo4j.bookmark.BookmarkManager` -interface and it's only implementation `org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager` are gone and are not needed anymore. +interface and its only implementation `org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager` are gone and are not needed anymore. SDN uses Bookmarks for all transactions, without configuration. You can remove the bean declaration of `CaffeineBookmarkManager` as well as the the dependency to `com.github.ben-manes.caffeine:caffeine`. diff --git a/src/main/asciidoc/appendix/neo4j-client.adoc b/src/main/asciidoc/appendix/neo4j-client.adoc index d9b652f3c..e6e930711 100644 --- a/src/main/asciidoc/appendix/neo4j-client.adoc +++ b/src/main/asciidoc/appendix/neo4j-client.adoc @@ -95,7 +95,7 @@ NOTE: Make sure you use the same driver instance for the client as you used for in case you have enabled transactions. The client won't be able to synchronize transactions if you use another instance of a driver. -Our Spring Boot starter provide a ready to use bean of the Neo4j Client that fit the environment (imperative or reactive) and you usually don't have to configure your own 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. == Usage @@ -176,19 +176,19 @@ ResultSummary resultSummary = imperativeClient SummaryCounters counters = resultSummary.counters(); System.out.println(counters.nodesDeleted() + " nodes have been deleted") ---- -<.> Here the query is triggered immediate. +<.> Here the query is immediately triggered. === Mapping parameters -Queries can contain named parameters (`$someName`). -The Neo4j client allows comfortable binding to those. +Queries can contain named parameters (`$someName`) and the Neo4j client makes it easy to bind values to them. -NOTE: The client doesn't check whether all parameters are bound or whether there are to many values. +NOTE: The client doesn't check whether all parameters are bound or whether there are too many values. That is left to the driver. -However the client prevents you from using a parameter name twice. +However, the client prevents you from using a parameter name twice. -You can either map simple types that the Java driver understands or complex classes. -Please have a look at the https://neo4j.com/docs/driver-manual/current/cypher-values/#driver-neo4j-type-system[drivers manual], to see which simple types are understood. +You can either bind simple types that the Java driver understands without conversion or complex classes. +For complex classes you need to provide a binder function as shown in <>. +Please have a look at the https://neo4j.com/docs/driver-manual/current/cypher-workflow/#driver-type-mapping[drivers manual], to see which simple types are supported. [[neo4j-client-mapping-simple-types]] [source,java] @@ -282,14 +282,14 @@ Mono summary = client }) .run(); ---- -<.> The with method allows for specifying the binder function. +<.> The `with` method allows for specifying the binder function. === Working with result objects Both clients return collections or publishers of maps (`Map`). -Those maps corresponds exactly with the records that a query might have produced. +Those maps correspond exactly with the records that a query might have produced. -In addition, you can plugin your own `BiFunction` through `fetchAs` to reproduce your domain object. +In addition, you can plug in your own `BiFunction` through `fetchAs` to reproduce your domain object. [[neo4j-client-reader]] [source,java] diff --git a/src/main/asciidoc/faq/faq.adoc b/src/main/asciidoc/faq/faq.adoc index 54acb5fbd..e463d5c93 100644 --- a/src/main/asciidoc/faq/faq.adoc +++ b/src/main/asciidoc/faq/faq.adoc @@ -13,7 +13,7 @@ or of course with a simple script upfront. === 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 Boots conventions applied): +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): [source,properties] ---- @@ -47,7 +47,7 @@ include::../../../../src/test/java/org/springframework/data/neo4j/documentation/ NOTE: Be careful that you don't mix up entities retrieved from one database with another database. 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 inevitable store the wrong entities in the wrong database. +Or worse, you could inevitably store the wrong entities in the wrong database. == Do I need specific configuration so that transactions work seamless with a Neo4j Causal Cluster? @@ -82,13 +82,13 @@ You are free to use the following, equivalent Spring Data annotations: == How do I use assigned ids? -Just `@Id` without `@GeneratedValue` and fill your id attribute via a constructor parameter or a setter or _wither_. +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. == How do I use externally generated ids? We provide the interface `org.springframework.data.neo4j.core.schema.IdGenerator`. -Implement it anyway you want and configure your implementation like this: +Implement it in any way you want and configure your implementation like this: [source,java] .ThingWithGeneratedId.java @@ -124,7 +124,7 @@ NOTE: Setters are not required on non-final fields for the id. == Do I have to create repositories for each domain class? No. -Have a look at the <> and find the `Neo4jTemplate` respectively the `ReactiveNeo4jTemplate.` +Have a look at the <> and find the `Neo4jTemplate` or the `ReactiveNeo4jTemplate`. Those templates know your domain and provide all necessary basic CRUD methods for retrieving, writing and counting entities. @@ -229,7 +229,7 @@ The following dependency is required for the solutions described above: [source,xml,subs="verbatim,attributes"] ---- - {springGroupId} + {neo4jGroupId} {artifactId} {spring-data-neo4j-version} diff --git a/src/main/asciidoc/getting-started/getting-started.adoc b/src/main/asciidoc/getting-started/getting-started.adoc index 5ae4ad653..c42026bed 100644 --- a/src/main/asciidoc/getting-started/getting-started.adoc +++ b/src/main/asciidoc/getting-started/getting-started.adoc @@ -5,7 +5,7 @@ We provide a Spring Boot starter for SDN. Please include the starter module via your dependency management and configure the bolt URL to use, for example `org.neo4j.driver.uri=bolt://localhost:7687`. The starter assumes that the server has disabled authentication. As the SDN starter depends on the starter for the Java Driver, all things regarding configuration said there, apply here as well. -For a reference of the available properties, use your IDEs autocompletion in the `org.neo4j.driver` namespace or look at the link:{java-driver-starter-href}/blob/master/docs/manual.adoc[dedicated manual]. +For a reference of the available properties, use your IDEs autocompletion in the `org.neo4j.driver` namespace or look at the link:{java-driver-starter-href}/blob/master/docs/manual/index.adoc[dedicated manual]. SDN supports @@ -14,7 +14,6 @@ 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. -Have a look at the link:{gh-base}/tree/master/examples[examples directory] for all examples. == Prepare the database @@ -65,7 +64,7 @@ As this starter is not yet on the initializer, you will have to add the followin .Inclusion of the spring-data-neo4j-spring-boot-starter in a Maven project ---- - {groupId} + {groupIdStarter} {artifactIdStarter} ---- @@ -94,7 +93,7 @@ The dependency for Gradle looks like this and must be added to `build.gradle`: .Inclusion of the spring-data-neo4j-spring-boot-starter in a Gradle project ---- dependencies { - implementation '{groupId}:{artifactIdStarter}' + implementation '{groupIdStarter}:{artifactIdStarter}' } ---- @@ -114,7 +113,7 @@ org.neo4j.driver.authentication.password=secret This is the bare minimum of what you need to connect to a Neo4j instance. -NOTE: It is not necessary to add any programmatically configuration of the driver when you use this starter. +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 your domain @@ -127,9 +126,9 @@ Our domain layer should accomplish two things: === Example Node-Entity SDN fully supports unmodifiable entities, for both Java and `data` classes in Kotlin. -Therefor we will focus on immutable entities here, <> shows a such an entity. +Therefore we will focus on immutable entities here, <> shows a such an entity. -NOTE: SDN supports all data types the Neo4j Java Driver supports, see https://neo4j.com/docs/driver-manual/current/cypher-values/#driver-neo4j-type-system[Map Neo4j types to native language types] inside the chapter "The Cypher type system". +NOTE: SDN supports all data types the Neo4j Java Driver supports, see https://neo4j.com/docs/driver-manual/current/cypher-workflow/#driver-type-mapping[Map Neo4j types to native language types] inside the chapter "The Cypher type system". Future versions will support additional converters. [source,java] @@ -150,9 +149,9 @@ We also provide generators for UUIDs. <.> This defines a relationship to a class of type `PersonEntity` and the relationship type `ACTED_IN` <.> This is the constructor to be used by your application code. -As a general remark: Immutable entities using internally generated ids are a bit contradictory, as SDN needs a way to set the field with the value generated by the database. +As a general remark: immutable entities using internally generated ids are a bit contradictory, as SDN needs a way to set the field with the value generated by the database. -If you don't find a good business key or don't want to use a generator for IDs, here's the same entity using the internally generated id together with a businesses constructor and a so called _wither_-Method, that is used by SDN: +If you don't find a good business key or don't want to use a generator for IDs, here's the same entity using the internally generated id together with a regular constructor and a so called _wither_-Method, that is used by SDN: [source,java] [[movie-entity-with-wither]] @@ -204,7 +203,7 @@ https://projectlombok.org/[Project Lombok] is an alternative if you want or need === Declaring Spring Data repositories You basically have two options here: -You can work store agnostic with SDN and make your domain specific extends one of +you can work in a store-agnostic fashion with SDN and make your domain specific extend one of * `org.springframework.data.repository.Repository` * `org.springframework.data.repository.CrudRepository` @@ -213,11 +212,11 @@ You can work store agnostic with SDN and make your domain specific extends one o Choose imperative and reactive accordingly. -WARNING: While technically not prohibited, it is not recommended to mix imperative and reactive database access in the same application. +WARNING: While technically not prohibited, it is not recommended mixing imperative and reactive database access in the same application. We won't support you with scenarios like this. The other option is to settle on a store specific implementation and gain all the methods we support out of the box. -The advantage of this approach is also it's biggest disadvantage: Once out, all those methods will be part of your API. +The advantage of this approach is also its biggest disadvantage: once out, all those methods will be part of your API. Most of the time it's harder to take something away, than to add stuff afterwards. Furthermore, using store specifics leaks your store into your domain. From a performance point of view, there is no penalty. diff --git a/src/main/asciidoc/introduction-and-preface/building-blocks.adoc b/src/main/asciidoc/introduction-and-preface/building-blocks.adoc index a9b4b5774..71425542d 100644 --- a/src/main/asciidoc/introduction-and-preface/building-blocks.adoc +++ b/src/main/asciidoc/introduction-and-preface/building-blocks.adoc @@ -10,7 +10,7 @@ All configuration options of the driver are accessible in the namespace `spring. The driver bean provides imperative, asynchronous and reactive methods to interact with Neo4j. You can use all transaction methods the driver provides on that bean such as https://neo4j.com/docs/driver-manual/4.0/terminology/#term-auto-commit[auto-commit transactions], -https://neo4j.com/docs/driver-manual/4.0/terminology/#term-auto-commit[transaction functions] and unmanaged transactions. +https://neo4j.com/docs/driver-manual/4.0/terminology/#term-transaction-function[transaction functions] and unmanaged transactions. Be aware that those transactions are not tight to an ongoing Spring transaction. Integration with Spring Data and Spring's platform or reactive transaction manager starts at the <>. diff --git a/src/main/asciidoc/introduction-and-preface/introduction.adoc b/src/main/asciidoc/introduction-and-preface/introduction.adoc index 4c5b0640e..a2032b8db 100644 --- a/src/main/asciidoc/introduction-and-preface/introduction.adoc +++ b/src/main/asciidoc/introduction-and-preface/introduction.adoc @@ -1,7 +1,7 @@ [[introduction]] = Your way through this document -If you already familiar with the core concepts of Spring Data, head straight to <>. +If you are already familiar with the core concepts of Spring Data, head straight to <>. This chapter will walk you through different options of configuring an application to connect to a Neo4j instance and how to model your domain. In most cases, you will need a domain. diff --git a/src/main/asciidoc/introduction-and-preface/preface.adoc b/src/main/asciidoc/introduction-and-preface/preface.adoc index cc22a85e9..15fa18199 100644 --- a/src/main/asciidoc/introduction-and-preface/preface.adoc +++ b/src/main/asciidoc/introduction-and-preface/preface.adoc @@ -1,7 +1,7 @@ [[preface.nosql]] = NoSQL and Graph databases -A graph database is a storage engine that is specialized in storing and retrieving vast networks of information. +A graph database is a storage engine that specializes in storing and retrieving vast networks of information. It efficiently stores data as nodes with relationships to other or even the same nodes, thus allowing high-performance retrieval and querying of those structures. Properties can be added to both nodes and relationships. Nodes can be labelled by zero or more labels, relationships are always directed and named. @@ -25,7 +25,6 @@ Here is a list of useful resources: * The https://neo4j.com/docs/[Neo4j documentation] introduces Neo4j and contains links to getting started guides, reference documentation and tutorials. * The https://neo4j.com/sandbox/[online sandbox] provides a convenient way to interact with a Neo4j instance in combination with the online https://neo4j.com/developer/get-started/[tutorial]. * Neo4j https://neo4j.com/developer/java/[Java Bolt Driver] -* https://neo4j.com/docs/ogm-manual/current/[Neo4j Object Graph Mapper (OGM) Library] * Several https://neo4j.com/books/[books] available for purchase and https://www.youtube.com/neo4j[videos] to watch. [[preface.spring-data]] @@ -53,7 +52,7 @@ There are a lot of articles, blog entries and books on the matter - take a look == What is Spring Data Neo4j The current Spring Data Neo4j is the successor to Spring Data Neo4j + Neo4j-OGM. -The separate layer of Neo4j-OGM (Neo4j Object Graph Mapper) has been replaced by Spring infrastructure, but the basic concepts of an Object Graph Mapper (OGM) still apply: +The separate layer of Neo4j-OGM (Neo4j Object Graph Mapper) has been replaced by Spring infrastructure, but the basic concepts of an Object Graph Mapper (OGM) still apply. An OGM maps nodes and relationships in the graph to objects and references in a domain model. Object instances are mapped to nodes while object references are mapped using relationships, or serialized to properties (e.g. references to a Date). @@ -63,7 +62,7 @@ It also provides the flexibility to the developer to supply custom queries where === 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://pivotal.io[Pivotal's] Spring Data Team. +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. SDN relies completely on the https://github.com/neo4j/neo4j-java-driver[Neo4j Java Driver], without introducing another "driver" or "transport" layer between the mapping framework and the driver. The Neo4j Java Driver - sometimes dubbed Bolt or the Bolt driver - is used as a protocol much like JDBC is with relational databases. @@ -85,11 +84,11 @@ SDN has several features not present in SDN+OGM, notably === 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 Spring Data Neo4j as its backend for the heavy lifting of mapping nodes and relationships into domain object. -The new SDN *does not need* and *does not support* 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. +The current SDN *does not need* and *does not support* Neo4j-OGM. SDN uses Spring Data's mapping context exclusively for scanning classes and building the meta model. -While this pins SDN to the Spring eco systems, it has several advantages, among them the smaller footprint in regards of CPU and memory usage and especially, all the features of Springs mapping context. +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. === Does SDN support connections over HTTP to Neo4j? diff --git a/src/main/asciidoc/object-mapping/mapping.adoc b/src/main/asciidoc/object-mapping/mapping.adoc index d5748ea81..100afc05b 100644 --- a/src/main/asciidoc/object-mapping/mapping.adoc +++ b/src/main/asciidoc/object-mapping/mapping.adoc @@ -163,7 +163,7 @@ In general there is no limitation of relationships / hops for creating the queri SDN parses the whole reachable graph from your modelled nodes. This said, when there is the idea of mapping a relationship bidirectional, meaning you define the relationship on both ends of your entity, -you might do not only get what you are expecting. +you might get more than what you are expecting. Consider an example where a _movie_ has _actors_, and you want to fetch a certain movie with all its actors. This won't be problematical if the relationship from _movie_ to _actor_ were just unidirectional. @@ -318,10 +318,10 @@ That leaves the assignment itself: The generated value will be stable and there won’t be a need to change it later on. * Disadvantage: The generated strategy is applied on the application side of things. In those days most applications will be deployed in more than one instance to scale nicely. -If your strategy is prone to generate duplicates than inserts will fail as uniques of the primary key will be violated. +If your strategy is prone to generate duplicates then inserts will fail as the uniqueness property of the primary key will be violated. So while you don’t have to think about a unique business key in this scenario, you have to think more what to generate. -You have several options to role your own ID generator. +You have several options to roll out your own ID generator. One is a POJO implementing a generator: .Naive sequence generator diff --git a/src/main/asciidoc/object-mapping/projections.adoc b/src/main/asciidoc/object-mapping/projections.adoc index e39100cb4..948eb3483 100644 --- a/src/main/asciidoc/object-mapping/projections.adoc +++ b/src/main/asciidoc/object-mapping/projections.adoc @@ -19,17 +19,17 @@ The domain type is the type that has been defined through the repository declara Interface based projections will always be dynamic proxies to the underlying domain type. The names of the accessors defined on such interfaces (like `getName`) must resolve to properties (here: `name`) that are present on the projected entity. Whether those properties have accessors or not on the domain type is not relevant, as long as they can be accessed through -the common Spring Data infrastructure. The later is ensure already, as the domain type wouldn't be a persistent entity in +the common Spring Data infrastructure. The latter is already ensured, as the domain type wouldn't be a persistent entity in the first place. DTO based projections are somewhat more flexible when used with custom queries. While the standard query is derived from the original domain type and therefore only the properties and relationship beeing defined there can be used, custom queries can add additional properties. -The rules are as follows: First, the properties of the domain type are used to populate the DTO. In case the DTO declare +The rules are as follows: first, the properties of the domain type are used to populate the DTO. In case the DTO declares additional properties - via accessors or fields - Spring Data Neo4j looks in the resulting record for matching properties. 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 no maps. +or of known persistent entites. Collections of those are supported, but maps are not. === A full example diff --git a/src/main/asciidoc/object-mapping/sdc-object-mapping.adoc b/src/main/asciidoc/object-mapping/sdc-object-mapping.adoc index 9bbcc326a..60530d5cc 100644 --- a/src/main/asciidoc/object-mapping/sdc-object-mapping.adoc +++ b/src/main/asciidoc/object-mapping/sdc-object-mapping.adoc @@ -208,7 +208,7 @@ Instead, defaulting of properties is handled within the factory method. * _Try to stick to immutable objects_ -- Immutable objects are straightforward to create as materializing an object is then a matter of calling its constructor only. -Also, this avoids your domain objects to be littered with setter methods that allow client code to manipulate the objects state. +Also, this prevents your domain objects from being littered with setter methods that allow client code to manipulate the objects state. If you need those, prefer to make them package protected so that they can only be invoked by a limited amount of co-located types. Constructor-only materialization is up to 30% faster than properties population. * _Provide an all-args constructor_ -- diff --git a/src/main/asciidoc/testing/testing.adoc b/src/main/asciidoc/testing/testing.adoc index edbf52edf..7a0663164 100644 --- a/src/main/asciidoc/testing/testing.adoc +++ b/src/main/asciidoc/testing/testing.adoc @@ -3,7 +3,7 @@ == Without Spring Boot -We work a lot with our abstract base classes for configuration in our own integration tests. They can be use like this: +We work a lot with our abstract base classes for configuration in our own integration tests. They can be used like this: [source,java] .One possible test setup without Spring Boot @@ -50,7 +50,7 @@ Similar classes are provided for reactive tests. == With Spring Boot and `@DataNeo4jTest` Spring Boot offers `@DataNeo4jTest` through `org.springframework.boot:spring-boot-starter-test`. -The later brings in `org.springframework.boot:spring-boot-test-autoconfigure` which contains the annotion and the +The latter brings in `org.springframework.boot:spring-boot-test-autoconfigure` which contains the annotation and the required infrastructure code. [source,xml,subs="verbatim,attributes"] @@ -63,8 +63,6 @@ required infrastructure code. ---- -Or with Gradle - [source,groovy,subs="verbatim,attributes"] .Include Spring Boot Starter Test in a Gradle build ---- @@ -74,7 +72,7 @@ dependencies { ---- `@DataNeo4jTest` is a Spring Boot https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-testing[test slice]. -The test slice provides all the necessary infrastructure for tests using Neo4j: A transaction manager, a client, a template and declared repositories, in their imperative or reactive variants, +The test slice provides all the necessary infrastructure for tests using Neo4j: a transaction manager, a client, a template and declared repositories, in their imperative or reactive variants, depending on reactive dependencies present or not. The test slice already includes `@ExtendWith(SpringExtension.class)` so that it runs automatically with JUnit 5 (JUnit Jupiter). @@ -89,12 +87,12 @@ for the infrastructure to select the correct transaction manager. The test slice does not bring in an embedded database or any other connection setting. It is up to you to use an appropriate connection. -We recommend one of two options: Either use the https://www.testcontainers.org/modules/databases/neo4j/[Neo4j Testcontainers module] +We recommend one of two options: either use the https://www.testcontainers.org/modules/databases/neo4j/[Neo4j Testcontainers module] or the Neo4j test harness. While Testcontainers is a known project with modules for a lot of different services, Neo4j test harness is rather unknown. It is an embedded instance that is especially useful when testing stored procedures as described in https://medium.com/neo4j/testing-your-neo4j-based-java-application-34bef487cc3c[Testing your Neo4j-based Java application]. The test harness can however be used to test an application as well. -As it brings up a database inside the same JVM as your application, performance and timings may not reassemble your production setup. +As it brings up a database inside the same JVM as your application, performance and timings may not resemble your production setup. For your convinience we provide three possible scenarios, Neo4j test harness 3.5 and 4.0 as well as Testcontainers Neo4j. We provide different examples for 3.5 and 4.0 as the test harness changed between those versions. @@ -111,7 +109,7 @@ You need the following dependencies to run <>: org.neo4j.test neo4j-harness - 3.5.21 + 3.5.23 test ---- @@ -190,7 +188,7 @@ You need the following dependencies to run <>: org.neo4j.test neo4j-harness - 4.0.8 + {neo4j-version} test @@ -261,10 +259,10 @@ class MovieRepositoryTest { } ---- <.> Entrypoint to create an embedded Neo4j -<.> Don't need Neoj4's HTTP server +<.> Disable the unneeded Neo4j HTTP server <.> This is a Spring Boot annotation that allows for dynamically registered application properties. We overwrite the corresponding Neo4j settings. -<.> Shutdown Neo4j after all tests. +<.> Shut down Neo4j after all tests. [[dataneo4jtest-testcontainers]] @@ -278,7 +276,7 @@ You need the following dependencies: org.testcontainers neo4j - 1.14.2 + 1.14.3 test ---- 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 e3e0ad034..8aa6d1f9d 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 @@ -1,7 +1,7 @@ /** * This package contains configuration related support classes that can be used for application specific, annotated - configuration classes. The abstract base classes are helpful if you don't rely on Spring Boots autoconfiguration. + configuration classes. The abstract base classes are helpful if you don't rely on Spring Boot's autoconfiguration. The package provides some additional annotations that enable auditing. * */