/gs-accessing-data-neo4j

Accessing Data with Neo4j :: Learn how to persist objects and relationships in Neo4j's NoSQL data store.

Primary LanguageJava

tags projects
spring-data
neo4j
spring-data-neo4j

This guide walks you through the process of using Spring Data to build an application with Neo4j.

What you’ll build

You’ll use Neo4j’s NoSQL graph-based data store to build an embedded Neo4j server, store entities and relationships, and develop queries.

What you’ll need

Define a simple entity

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[]

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.

Create simple queries

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[]

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.

Enable Neo4j Repositories

To use Neo4j, you need to active it.

src/main/java/hello/ApplicationConfig.java

link:complete/src/main/java/hello/ApplicationConfig.java[]
  • @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 the hello 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

Create an Application class with all the components.

src/main/java/hello/Application.java

link:complete/src/main/java/hello/Application.java[]

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.

Summary

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.