This project modified the original project to demonstrate the speed of inserts.
tags: [spring-data, neo4j] projects: [spring-data-neo4j] --- :toc: :icons: font :source-highlighter: prettify :project_id: gs-accessing-data-neo4j This guide walks you through the process of using Spring Data to build an application with Neo4j.
You’ll use Neo4j’s NoSQL graph-based data store to build an embedded Neo4j server, store entities and relationships, and develop queries.
Neo4j captures entities and their relationships, with both aspects being of equal importance. Imagine you are modeling a system where you store a record for each person. But you also want to track a person’s co-workers (teammates
in this example). With Neo4j, you can capture all that with some simple annotations.
src/main/java/hello/Person.java
link:complete/src/main/java/hello/Person.java[role=include]
Here you have a Person
class that has only one attribute, the name
. You have two constructors, an empty one as well as one for the name
. To use Neo4j later on, you need the empty constructor. The name-based one is for convenience.
Note
|
In this guide, the typical getters and setters are omitted for brevity. |
The Person
class is annotated @NodeEntity
. When Neo4j stores it, it results in the creation of a new node. This class also has an id
marked @GraphId
. Neo4j uses @GraphId
internally to track the data.
The next important piece is the set of teammates
. It is a simple Set<Person>
, but marked up as @RelatedTo
. This means that every member of this set is expected to also exist as a separate Person
node. Note how the direction is set to BOTH
. This means that when you query the TEAMMATE
relationship, Spring Data Neo4j will ignore the direction of the relationship. There is also a @Fetch
annotation on this field as well. This causes the teammates to be eagerly retrieved. Otherwise you would have to use neo4jTemplate.fetch().
With the worksWith()
method, you can easily link people together.
Finally, you have a convenient toString()
method to print out the person’s name and that person’s co-workers.
Spring Data Neo4j is focused on storing data in Neo4j. But it inherits functionality from the Spring Data Commons project, including the ability to derive queries. Essentially, you don’t have to learn the query language of Neo4j, but can simply write a handful of methods and the queries are written for you.
To see how this works, create an interface that queries Person
nodes.
src/main/java/hello/PersonRepository.java
link:complete/src/main/java/hello/PersonRepository.java[role=include]
PersonRepository
extends the CrudRepository
interface and plugs in the type it operates on: Person
. Out-of-the-box, this interface comes with many operations, including standard CRUD (create-read-update-delete) operations.
But you can define other queries as needed by simply declaring their method signature. In this case, you added findByName
, which seeks nodes of type Person
and finds the one that matches on name
. You also have findByTeammatesName
, which looks for a Person
node, drills into each entry of the teammates
field, and matches based on the teammate’s name
.
To use Neo4j, you need to active it.
src/main/java/hello/ApplicationConfig.java
link:complete/src/main/java/hello/ApplicationConfig.java[role=include]
-
@Configuration
flags this class as a source for more bean definitions. -
@EnableNeo4jRepositories
tells Spring to pull in all the bean definitions needed to activate Neo4j. -
This class extends
Neo4jConfiguration
, and adapter from which we can specify key settings. -
Speaking of settings,
setBasePackage
tells Neo4j to scan thehello
package for repositories. -
It also creates a
GraphDatabaseService
based on the embedded version of Neo4j (handy for testing!)
Let’s wire this up and see what it looks like!
Create an Application class with all the components.
src/main/java/hello/Application.java
link:complete/src/main/java/hello/Application.java[role=include]
You autowire an instance of PersonRepository
that you defined earlier. Spring Data Neo4j will dynamically create a concrete class that implements that interface and will plug in the needed query code to meet the interface’s obligations.
The public static void main
uses Spring Boot’s SpringApplication.run()
to launch the application and invoke the CommandLineRunner
that builds the relationships.
In this case, you create three local Person
s, Greg, Roy, and Craig. Initially, they only exist in memory. It’s also important to note that no one is a teammate of anyone (yet).
To store anything in Neo4j, you must start a transaction using the graphDatabase
. In there, you will save each person. Then, you fetch each person, and link them together.
At first, you find Greg and indicate that he works with Roy and Craig, then persist him again. Remember, the teammate relationship was marked as BOTH
, that is, bidirectional. That means that Roy and Craig will have been updated as well.
That’s why when you need to update Roy, it’s critical that you fetch that record from Neo4j first. You need the latest status on Roy’s teammates before adding Craig to the list.
Why is there no code that fetches Craig and adds any relationships? Because you already have! Greg earlier tagged Craig as a teammate, and so did Roy. That means there is no need to update Craig’s relationships again. You can see it as you iterate over each team member and print their information to the console.
Finally, check out that other query where you look backwards, answering the question "who works with whom?"
You should see something like this (with other stuff like queries as well):
Before linking up with Neo4j... Greg's teammates include Roy's teammates include Craig's teammates include Lookup each person by name... Greg's teammates include - Craig - Roy Roy's teammates include - Craig - Greg Craig's teammates include - Roy - Greg Looking up who works with Greg... Roy works with Greg. Craig works with Greg.
You can see from the output that initially no one is connected by any relationship. Then after adding people in, they are tied together. Finally, you can see the handy query that looks up people based on teammate.
Congratulations! You just set up an embedded Neo4j server, stored some simple, related entities, and developed some quick queries.
Note
|
If you’re interesting in exposing Neo4j repositories with a hypermedia-based RESTful front end with little effort, you might want to read Accessing Neo4j Data with REST. |