상세 컨텐츠

본문 제목

Spring Reactive Neo4j

카테고리 없음

by ymconmencoe1981 2020. 10. 11. 08:05

본문



  1. I'm starting a new Spring boot project and I've chosen a neo4j graph database as there is a lot of connected data. I would like to use Reactive Streams in the project as there is a lot of push notifications from the server to the client. I'm looking at using Spring Webflux for this reason.
  2. I'm starting a new Spring boot project and I've chosen a neo4j graph database as there is a lot of connected data. I would like to use Reactive Streams in the project as there is a lot of push notifications from the server to the client. I'm looking at using Spring Webflux for this reason.
  3. Jan 22, 2020 Hello! Is there a way to do Database Selection via configuring the new SDN/RX spring driver? I cannot find a property to facilitate this. Presently the only way I can to perform database selection is to build a SessionConfig and pass that to the Driver.session(config). This solution will not work for Spring Repositories where the Driver and Session creation is handled behind Spring's.

This post introduces what’s been happening in Spring Data Neo4j recently.

The frost. Aug 06, 2020  The Neo4j configuration is very straight forward and defines the connection setting for the application to connect to the server. Similar to the most of the other spring data modules, this is a spring configuration which can be defined as XML or Java configuration. Roland drivers windows 7.


You will learn about the new features and the simplification of the programming model, find out what has changed under the cover, such as smarter querying for better performance. You will also read about the upcoming features. Don’t miss the opportunity to fill in our survey to bring your ideas in the roadmap!
For over half a year the SDN/OGM team has been working on new features in Neo4j Object Graph Mapping library (OGM) and Spring Data Neo4j (SDN) framework. We are happy to announce the release of OGM 3.0 and SDN 5.0.
We’re also welcoming Gerrit Meier to the Spring Data Neo4j team within Neo4j engineering, who besides developing and improving the libraries will also work closely with the Pivotal team and our users, customers and field engineers to provide an even better experience for you.
If you attended GraphConnect New York you might have seen the “Building Microservices with Spring Cloud & Spring Boot” training (with a section on Spring Data Neo4j 5.0) by Kenny Bastani.

The “Spring Data Neo4j 5.0” talk by Nicolas and Gerrit was repeated as Neo4j Online Meetup, that you can watch below:

Software menghitung rab free

For those Java developers who are not familiar with it, Neo4j-OGM is an object-graph mapping library for Neo4j, optimised for server-based installations utilising Cypher. It aims to simplify development with Neo4j, and similar to JPA or Hibernate, it uses annotations on simple POJO domain objects to provide mapping metadata.
Spring Data Neo4j is a Spring Data project for Neo4j. It uses Neo4j-OGM under the hood (very much like Spring Data JPA uses JPA) and provides functionality known from the Spring Data world, like repositories, derived finders or auditing.

New in Neo4j-OGM 3.0


There are many new features in both OGM and SDN. Note that all new OGM features are automatically available for SDN users as well, so even if you use SDN directly, or through Spring Boot, you should read this section.

Dynamic properties


Dynamic properties was one of the most requested features. This allows you to take advantage of the fact that Neo4j is a database with an optional schema and can map arbitrary properties on entities in the graph to a Map field in your node or relationship entity (and vice versa).
To use this feature simply annotate a Map with new @Properties annotation. The allowed keys in the map are either String or Enum, the values may be any types defined by the Cypher query language. The property keys are constructed by concatenating the field name (or prefix), the delimiter (“.” by default) and the key in the map.
A Map with a key of note and a value A note about user would be mapped to a node property custom.note with the value A note about user. See the documentation for more details.

Schema-Based Loading


One of the fundamental design decisions in OGM, which aims to reduce the number of queries, is that an entity and all relationships up to certain degree are loaded using a single query. This is very cheap in Neo4j thanks to its index-free adjacency (compared to relational databases, where each level would mean another JOIN). Starting with the previous version, SDN4, when an entity was loaded up to certain depth it was queried by following pattern:
This works very well when the domain classes match your graph 1:1, but inefficiencies may arise in certain situations, resulting in loading more data than needed:

  • Direction of relationships is ignored
  • Relationships and nodes not in the class model are loaded anyway
  • Nodes at the beginning of the path are returned multiple times

That was especially problematic with higher depths and when a node had a large number of irrelevant (for our POJO) relationships that were fetched and then thrown away.
We have now switched to a new load strategy based on a schema derived automatically from class metadata. It uses nested pattern comprehensions generated from the schema. The final part of load queries now look usually like this:

Spring Reactive Neo4j Software


Querying a Person node with two different relationships to Organisation.
This has several advantages:

  • Only data which will be mapped are fetched
  • It respects direction and type of relationship in the class metadata
  • Avoids fetching duplicates (it doesn’t completely eliminate them when there are cycles though)
  • It nests over multiple levels of fetching

While we have extensive test coverage for various entity models (inheritance hierarchies, generic entities, etc.), as a preemptive workaround for any issues there is a way to fall back to the old style of querying by (for a single session):
or globally:
Also note that it is not possible to query for unlimited depth (depth = -1) with the new load strategy (which was a dangerous option in the first place).
This is a first step, which makes further enhancements possible – like loading only relationships you are interested in, loading only some, not all node/relationship properties – these will come in future versions.

New Id Management


In Spring Data Neo4j 4, a mandatory specific field for entity id had to be used (of type java.lang.Long, either named id, or annotated with the @GraphId annotation). If an application wanted to lookup entities by another attribute, it had to add a primary index via

Spring Reactive Neo4j

@Index(primary = true, unique = true).
While an id is still required on all entities, the behavior has been simplified by introducing the new @Id annotation. It replaces both @GraphId and the primary attribute and can be placed on any attribute with a simple type.
The generation of this id attribute is also now customizable. Out of the box, two strategies are provided: UUID generation and ids generated by Neo4j. Applications can also provide a custom generation strategy if needed.
These id’s will be used for looking up entities and for MERGE on the id field on save.

Spring Boot Neo4j Example

Field Access Only

Neo4j


Entity fields are now read from and written directly by the object mapper, not through annotated or derived setters.
This has been a major source of confusion in the past, and we hope this change makes the mapping easier. See the migration guide for more details.

Configuration Changes and Improvements


A new builder configuration class was introduced as a single place for configuring the OGM via properties. New constructors for SessionFactory and all drivers were added to allow creation of fully customised drivers. Also the driver class name is derived automatically from provided URI.
This provides two main benefits:

  • If you need to configure a setting not handled by OGM, you don’t need to wait for us to make it available
  • Custom configuration of embedded database for tests (with procedures or other settings, like enabling shell, etc.)

Example configuration using builder:

Neo4j sample data


Example configuration providing custom driver:

Internal Changes

 

Classpath scanning


Our own, custom classpath scanning and bytecode parsing has been dropped in favour of FastClasspathScanner and standard reflection. Performance tests show roughly same performance and we should provide better compatibility with environments with unusual classloader hierarchy.

New in Spring Data Neo4j 5.0

 

Spring Framework 5.0 and Java 8


Spring Data Neo4j 5.0 is built on top of Java 8, the new Spring Framework 5.0 and Spring Data 2.0. Using these foundations allows us to benefit from the latest enhancements in the Spring world.

Better Causal Cluster Support


In Neo4j, bookmarks are used to achieve causal consistency. Bookmark management in Spring Data Neo4j automates handling of transaction-bookmarks for Neo4j clusters (read your own writes) within an application.
Once it is enabled through @EnableBookmarkManagement it stores all bookmarks of finished transactions to an instance of BookmarkManager (needs to be provided by the user) and looks for methods annotated with @UseBookmark – similar to @Transactional – it is actually intended to be used together.
When this annotation is present, it uses the current set of bookmarks to start a new transaction, achieving causal consistency for that transaction. So you can choose for which methods you need to see your own changes (e.g., user profile management) and for which it doesn’t matter (e.g., a listing or recommendation).
Example of bookmark management configuration:

Neo4j


Example of @UseBookmark on a service method, which should use bookmark to be able to read previously created user:

Query methods


Query methods with derived queries (a.k.a., derived finders) are one of the flagship features of any Spring Data project. Support for derived finders has been improved in this release. See the relevant documentation for a comprehensive list of supported keywords. We are planning to end enhance this even further, so if you miss a keyword and think others would find it useful as well please fill in a feature request!

Projections


Sometimes you want to return a customized shape of your data, for performance or functional reasons. Spring Data 2.0 added new support for projections which extends our existing means to project result data. Spring Data Neo4j now provides an easy way to do that by defining a projection interface like this:
And then using it as a regular return type in your UserRepository like this:
This won’t change anything to the query side, but will reshape data returned by your repositories to get customized representations. Check more details in the documentation.

Migration


The migration from OGM 2.1 / SDN 4.2 to the new version should be straightforward for most of you. There are detailed migration guides in the documentation:

The Future of Spring Data Neo4j


We’re working on some exciting things for the next release.
One is reactive repositories built upon the upcoming async Bolt Driver (v1.5). Auditing support has been added to the core of Spring Data Neo4j. There is still some testing to do but it should be ready for prime time in a few weeks.
Some improvements for modeling and querying will be added soon, like removing the need for a default constructor on entity classes, support for persistence constructors, or the ability to use named queries. We also are looking to add better Kotlin support.

Spring Reactive Neo4j Free

Full Java 9 support is on the way. Even if SDN technically works on Java 9, we are working on making it fully compatible with the Jigsaw module system.

Feedback Survey


The team would love to hear your feedback on new features and current state of the two libraries. Please find a minute to fill in this short survey

Spring Reactive Neo4j Data

if you’re using SDN or OGM or plan to use it.

References

 

  • Spring Data Neo4j Reference Documentation (also includes general Spring Data reference in section 7 and OGM manual in sections 12-23)
  • Ask and discuss with the team and other users on the SDN/OGM Slack channel
  • Ask more involved questions on Stack Overflow using the tags for OGM and SDN.
  • Use the templates project for reporting issues. (They can also be used to bootstrap your projects.)

Thank You!


We want to thank the amazing team from our partner GraphAware for doing all the work around Neo4j-OGM and Spring Data Neo4j. Especially Frantisek Hartman and

Spring Reactive Neo4j Group

Nicolas Mervaillie did an outstanding job. Immediately after joining the team, Gerrit Meier quickly started to work on issues, examples and documentation and was the communication link to the Pivotal team.
Thanks a lot to Oliver Gierke – the Spring Data project lead from Pivotal – for his feedback, support and understanding. And of course many thanks to all our users

Spring Reactive Neo4j Vs

for using the libraries and especially for reporting feedback, issues and suggestions.



  1. I'm starting a new Spring boot project and I've chosen a neo4j graph database as there is a lot of connected data. I would like to use Reactive Streams in the project as there is a lot of push notifications from the server to the client. I'm looking at using Spring Webflux for this reason.
  2. I'm starting a new Spring boot project and I've chosen a neo4j graph database as there is a lot of connected data. I would like to use Reactive Streams in the project as there is a lot of push notifications from the server to the client. I'm looking at using Spring Webflux for this reason.
  3. Jan 22, 2020 Hello! Is there a way to do Database Selection via configuring the new SDN/RX spring driver? I cannot find a property to facilitate this. Presently the only way I can to perform database selection is to build a SessionConfig and pass that to the Driver.session(config). This solution will not work for Spring Repositories where the Driver and Session creation is handled behind Spring's.

This post introduces what’s been happening in Spring Data Neo4j recently.

The frost. Aug 06, 2020  The Neo4j configuration is very straight forward and defines the connection setting for the application to connect to the server. Similar to the most of the other spring data modules, this is a spring configuration which can be defined as XML or Java configuration. Roland drivers windows 7.


You will learn about the new features and the simplification of the programming model, find out what has changed under the cover, such as smarter querying for better performance. You will also read about the upcoming features. Don’t miss the opportunity to fill in our survey to bring your ideas in the roadmap!
For over half a year the SDN/OGM team has been working on new features in Neo4j Object Graph Mapping library (OGM) and Spring Data Neo4j (SDN) framework. We are happy to announce the release of OGM 3.0 and SDN 5.0.
We’re also welcoming Gerrit Meier to the Spring Data Neo4j team within Neo4j engineering, who besides developing and improving the libraries will also work closely with the Pivotal team and our users, customers and field engineers to provide an even better experience for you.
If you attended GraphConnect New York you might have seen the “Building Microservices with Spring Cloud & Spring Boot” training (with a section on Spring Data Neo4j 5.0) by Kenny Bastani.

The “Spring Data Neo4j 5.0” talk by Nicolas and Gerrit was repeated as Neo4j Online Meetup, that you can watch below:

Software menghitung rab free

For those Java developers who are not familiar with it, Neo4j-OGM is an object-graph mapping library for Neo4j, optimised for server-based installations utilising Cypher. It aims to simplify development with Neo4j, and similar to JPA or Hibernate, it uses annotations on simple POJO domain objects to provide mapping metadata.
Spring Data Neo4j is a Spring Data project for Neo4j. It uses Neo4j-OGM under the hood (very much like Spring Data JPA uses JPA) and provides functionality known from the Spring Data world, like repositories, derived finders or auditing.

New in Neo4j-OGM 3.0


There are many new features in both OGM and SDN. Note that all new OGM features are automatically available for SDN users as well, so even if you use SDN directly, or through Spring Boot, you should read this section.

Dynamic properties


Dynamic properties was one of the most requested features. This allows you to take advantage of the fact that Neo4j is a database with an optional schema and can map arbitrary properties on entities in the graph to a Map field in your node or relationship entity (and vice versa).
To use this feature simply annotate a Map with new @Properties annotation. The allowed keys in the map are either String or Enum, the values may be any types defined by the Cypher query language. The property keys are constructed by concatenating the field name (or prefix), the delimiter (“.” by default) and the key in the map.
A Map with a key of note and a value A note about user would be mapped to a node property custom.note with the value A note about user. See the documentation for more details.

Schema-Based Loading


One of the fundamental design decisions in OGM, which aims to reduce the number of queries, is that an entity and all relationships up to certain degree are loaded using a single query. This is very cheap in Neo4j thanks to its index-free adjacency (compared to relational databases, where each level would mean another JOIN). Starting with the previous version, SDN4, when an entity was loaded up to certain depth it was queried by following pattern:
This works very well when the domain classes match your graph 1:1, but inefficiencies may arise in certain situations, resulting in loading more data than needed:

  • Direction of relationships is ignored
  • Relationships and nodes not in the class model are loaded anyway
  • Nodes at the beginning of the path are returned multiple times

That was especially problematic with higher depths and when a node had a large number of irrelevant (for our POJO) relationships that were fetched and then thrown away.
We have now switched to a new load strategy based on a schema derived automatically from class metadata. It uses nested pattern comprehensions generated from the schema. The final part of load queries now look usually like this:

Spring Reactive Neo4j Software


Querying a Person node with two different relationships to Organisation.
This has several advantages:

  • Only data which will be mapped are fetched
  • It respects direction and type of relationship in the class metadata
  • Avoids fetching duplicates (it doesn’t completely eliminate them when there are cycles though)
  • It nests over multiple levels of fetching

While we have extensive test coverage for various entity models (inheritance hierarchies, generic entities, etc.), as a preemptive workaround for any issues there is a way to fall back to the old style of querying by (for a single session):
or globally:
Also note that it is not possible to query for unlimited depth (depth = -1) with the new load strategy (which was a dangerous option in the first place).
This is a first step, which makes further enhancements possible – like loading only relationships you are interested in, loading only some, not all node/relationship properties – these will come in future versions.

New Id Management


In Spring Data Neo4j 4, a mandatory specific field for entity id had to be used (of type java.lang.Long, either named id, or annotated with the @GraphId annotation). If an application wanted to lookup entities by another attribute, it had to add a primary index via

Spring Reactive Neo4j

@Index(primary = true, unique = true).
While an id is still required on all entities, the behavior has been simplified by introducing the new @Id annotation. It replaces both @GraphId and the primary attribute and can be placed on any attribute with a simple type.
The generation of this id attribute is also now customizable. Out of the box, two strategies are provided: UUID generation and ids generated by Neo4j. Applications can also provide a custom generation strategy if needed.
These id’s will be used for looking up entities and for MERGE on the id field on save.

Spring Boot Neo4j Example

Field Access Only

Neo4j


Entity fields are now read from and written directly by the object mapper, not through annotated or derived setters.
This has been a major source of confusion in the past, and we hope this change makes the mapping easier. See the migration guide for more details.

Configuration Changes and Improvements


A new builder configuration class was introduced as a single place for configuring the OGM via properties. New constructors for SessionFactory and all drivers were added to allow creation of fully customised drivers. Also the driver class name is derived automatically from provided URI.
This provides two main benefits:

  • If you need to configure a setting not handled by OGM, you don’t need to wait for us to make it available
  • Custom configuration of embedded database for tests (with procedures or other settings, like enabling shell, etc.)

Example configuration using builder:

Neo4j sample data


Example configuration providing custom driver:

Internal Changes

 

Classpath scanning


Our own, custom classpath scanning and bytecode parsing has been dropped in favour of FastClasspathScanner and standard reflection. Performance tests show roughly same performance and we should provide better compatibility with environments with unusual classloader hierarchy.

New in Spring Data Neo4j 5.0

 

Spring Framework 5.0 and Java 8


Spring Data Neo4j 5.0 is built on top of Java 8, the new Spring Framework 5.0 and Spring Data 2.0. Using these foundations allows us to benefit from the latest enhancements in the Spring world.

Better Causal Cluster Support


In Neo4j, bookmarks are used to achieve causal consistency. Bookmark management in Spring Data Neo4j automates handling of transaction-bookmarks for Neo4j clusters (read your own writes) within an application.
Once it is enabled through @EnableBookmarkManagement it stores all bookmarks of finished transactions to an instance of BookmarkManager (needs to be provided by the user) and looks for methods annotated with @UseBookmark – similar to @Transactional – it is actually intended to be used together.
When this annotation is present, it uses the current set of bookmarks to start a new transaction, achieving causal consistency for that transaction. So you can choose for which methods you need to see your own changes (e.g., user profile management) and for which it doesn’t matter (e.g., a listing or recommendation).
Example of bookmark management configuration:

Neo4j


Example of @UseBookmark on a service method, which should use bookmark to be able to read previously created user:

Query methods


Query methods with derived queries (a.k.a., derived finders) are one of the flagship features of any Spring Data project. Support for derived finders has been improved in this release. See the relevant documentation for a comprehensive list of supported keywords. We are planning to end enhance this even further, so if you miss a keyword and think others would find it useful as well please fill in a feature request!

Projections


Sometimes you want to return a customized shape of your data, for performance or functional reasons. Spring Data 2.0 added new support for projections which extends our existing means to project result data. Spring Data Neo4j now provides an easy way to do that by defining a projection interface like this:
And then using it as a regular return type in your UserRepository like this:
This won’t change anything to the query side, but will reshape data returned by your repositories to get customized representations. Check more details in the documentation.

Migration


The migration from OGM 2.1 / SDN 4.2 to the new version should be straightforward for most of you. There are detailed migration guides in the documentation:

The Future of Spring Data Neo4j


We’re working on some exciting things for the next release.
One is reactive repositories built upon the upcoming async Bolt Driver (v1.5). Auditing support has been added to the core of Spring Data Neo4j. There is still some testing to do but it should be ready for prime time in a few weeks.
Some improvements for modeling and querying will be added soon, like removing the need for a default constructor on entity classes, support for persistence constructors, or the ability to use named queries. We also are looking to add better Kotlin support.

Spring Reactive Neo4j Free

Full Java 9 support is on the way. Even if SDN technically works on Java 9, we are working on making it fully compatible with the Jigsaw module system.

Feedback Survey


The team would love to hear your feedback on new features and current state of the two libraries. Please find a minute to fill in this short survey

Spring Reactive Neo4j Data

if you’re using SDN or OGM or plan to use it.

References

 

  • Spring Data Neo4j Reference Documentation (also includes general Spring Data reference in section 7 and OGM manual in sections 12-23)
  • Ask and discuss with the team and other users on the SDN/OGM Slack channel
  • Ask more involved questions on Stack Overflow using the tags for OGM and SDN.
  • Use the templates project for reporting issues. (They can also be used to bootstrap your projects.)

Thank You!


We want to thank the amazing team from our partner GraphAware for doing all the work around Neo4j-OGM and Spring Data Neo4j. Especially Frantisek Hartman and

Spring Reactive Neo4j Group

Nicolas Mervaillie did an outstanding job. Immediately after joining the team, Gerrit Meier quickly started to work on issues, examples and documentation and was the communication link to the Pivotal team.
Thanks a lot to Oliver Gierke – the Spring Data project lead from Pivotal – for his feedback, support and understanding. And of course many thanks to all our users

Spring Reactive Neo4j Vs

for using the libraries and especially for reporting feedback, issues and suggestions.

<img style="cursor: pointer; display: block; margin-left: auto; margin-right: auto;" src="data:image/png;base64,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