Spring Data with the Neo4j graph database
In this tutorial we will have a look at the Neo4j graph database and will start to integrate it into our Spring project. We will also query a Neo4j database and perform various operations like:
- Create, Read, Update and Delete
- Establish relationships
- Query on the basis of relationships
Spring framework is an open source Java platform that provides MVC infrastructure support for developing robust Java applications very easily and very rapidly using recommended MVC pattern.
Neo4j
Neo4j is one of the most popular graph databases which stores data in nodes and provides relationships between them. It is written completely in Java.
In Neo4j uses another query language is used called Cypher Query Language (CQL), as opposed to the well know Structured Query Language (SQL). Some of best features of this graph database are:
- Open source
- Schema free
- NoSQL
- Graph database
A Graph Database is also known as a Graph Database Management System and is the one which stores data in the form of Graph structures. To establish comparisons between a GDBMS and an RDBMS, let’s compare their terminologies.
- Tables become Graphs.
- Rows are equivalent to Nodes.
- Columns and Data are turned to properties and their values.
- Constraints become relationships.
- Joins are used as Traversals.
Terminologies
Understanding concepts in Neo4j becomes easier if we can relate them to relational database structures. Let's see the close analogy Neo4j follows with a traditional MySQL system:
- A Graph is a collection of nodes and the relationships that connect those nodes.
- Nodes and Relationships contain properties to represent data.
- Properties are key-value pairs to represent data.
Advantages of Neo4j over RDBMS
The primary difference is that in a graph database, the relationships are stored at the individual record level, while in a relational database, the structure is defined at a higher level (the table definitions).
This has important advantages and disadvantages:
- A relational database is much faster when operating on huge numbers of records. In a graph database, each record has to be examined individually during a query in order to determine the structure of the data, while this is known ahead of time in a relational database.
- Relational databases use less storage space, because they don't have to store all of those relationships.
- The graph data model allows storage of all the connections of the node along with the node, so that there is no additional step in computing connected data apart from reading the node into memory.
Spring Data Neo4j
Spring Data comes in with excellent support for the Neo4j Graph database.
To start, let’s add the required Maven dependency in our project as:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
Let us also add Transaction support provided by the java Transaction API using its maven dependency:
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
Finally, we add the Java Validation API to validate against entities we’re going to create:
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
To check for latest Maven releases, check here.
Next, we need to know about services offered for Neo4j with Spring data. Basically, there are four:
- GraphRepository: This service is used to perform basic DB operations.
- GraphTemplate: Like other modules, this is a Spring template to perform Neo4j operations.
- CrudRepository: It is used to perform Neo4j CRUD operations with Cypher Query Language(CQL).
- PaginationAndSortingRepository: It is used to perform Paging and Sorting of Neo4j CQL Query results.
Neo4j Annotations
Now that we know about the services offered and have knowledge about the advantages of a Graph database, let’s start by understanding how Spring Data handles entities.
Configuring Spring data Neo4j
To start, we need to declare a GraphDatabaseService bean and enable automatic Neo4j repository generation. Let’s look at one of the beans defined here:
import org.Neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
@Configuration
@EnableNeo4jRepositories(basePackages="orders.db")
public class Neo4jConfig extends Neo4jConfiguration {
public Neo4jConfig() {
setBasePackage("orders");
}
@Bean(destroyMethod="shutdown")
public GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory()
.newEmbeddedDatabase("/tmp/graphdb");
}
}
The @EnableNeo4jRepositories annotation enables Spring Data Neo4j to automatically generate Neo4j repository implementations. Its basePackages is set so that it scans the orders.db package for interfaces that extend (directly or indirectly) any marker Repository interface.
Finally in the configuration class, we must define a GraphDatabaseService bean which will setup a connection with the Graph database. Let’s see how to do that:
@Bean(destroyMethod="shutdown")
public GraphDatabaseService graphDatabaseService(Environment env) {
return new SpringRestGraphDatabase(
"http://graphdbserver:7474/db/data/",
env.getProperty("db.username"), env.getProperty("db.password"));
}
Annotating Graph entities
Neo4j defines two type of entities: nodes and relationships. Node entities basically represent the things in our application, whereas relationship entities indicate how those things are related.
To start, let’s define a User entity.
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.data.neo4j.annotation.GraphId;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelatedTo;
@NodeEntity
public class Order {
@GraphId
private Long id;
private String customer;
private String type;
@RelatedTo(type="HAS_ITEMS")
private Set<Item> items = new LinkedHashSet<Item>();
...
}
Apart from the @NodeEntity annotation for the User entity, id is also annotated with @GraphId annotation as all entities in Neo4j must have a graph ID. The items property is annotated with @RelatedTo, indicating that an Order is related to a Set of Item. The type attribute simply labels the relationship.
The Item entity will be same. Let’s directly look at the relationship entity.
import org.springframework.data.neo4j.annotation.EndNode;
import org.springframework.data.neo4j.annotation.GraphId;
import org.springframework.data.neo4j.annotation.RelationshipEntity;
import org.springframework.data.neo4j.annotation.StartNode;
@RelationshipEntity(type="HAS_LINE_ITEM_FOR")
public class LineItem {
@GraphId
private Long id;
@StartNode
private Order order;
@EndNode
private Product product;
private int quantity;
...
}
What makes relationship entities special is that they connect two node entities. The @StartNode and @EndNode annotations are applied to properties that define each end of a relationship. In this case, the Order is the start node and the Product is the end node.
Finally, LineItem has a quantity property that will be persisted to the database when the relationship is created.
Define repository
Now that we’re done defining entities for nodes and relationships as well, let’s move to adding an important part of the Data access layer, the repositories. For Order entity, the corresponding repository will look like:
import orders.Order;
import org.springframework.data.neo4j.repository.GraphRepository;
public interface OrderRepository extends GraphRepository<Order> {}
Just like the other Spring Data projects, Spring Data Neo4j triggers repository generation for interfaces that extend the Repository interface. In this case, OrderRepository extends GraphRepository, which indirectly extends Repository. Therefore, Spring Data Neo4j will generate an implementation for OrderRepository at runtime.
Now that it’s done, we can use a handful of methods. Let have a look at some of them.
To save an order, simply do:
Order savedOrder = orderRepository.save(order);
To find a single order:
Order order = orderRepository.findOne(4L);
To get all orders:
EndResult<Order> allOrders = orderRepository.findAll();
To delete an order:
delete(order);
To delete an order using ID:
delete(orderId);
Adding custom query methods
We can also add custom query methods. Let’s jump to an example straightaway:
import java.util.List;
import orders.Order;
import org.springframework.data.neo4j.repository.GraphRepository;
public interface OrderRepository extends GraphRepository<Order> {
List<Order> findByCustomer(String customer);
List<Order> findByCustomerAndType(String customer, String type);
}
Conclusion
In this article, we learned how to configure and use one of the most popular Graph Database out there in Java, Neo4j. We also defined its repositories and added custom query methods to it.
In coming article, we will study about Reddis in Spring boot and its integration.
Stop by the homepage to compare and search for the best dev tools.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment