Introduction to Spring Data Neo4j – Spring Data Neo4j简介

最后修改: 2016年 7月 1日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

This article is an introduction to Spring Data Neo4j, the popular graph database.

本文是对Spring Data Neo4j的介绍,这是一个流行的图形数据库。

Spring Data Neo4j enables POJO based development for the Neo4j Graph Database and uses familiar Spring concepts such as a template classes for core API usage and provides an annotation based programming model.

Spring Data Neo4j为Neo4j图形数据库实现了基于POJO的开发,并使用了熟悉的Spring概念,如用于核心API的模板类,并提供了一个基于注解的编程模型。

Also, a lot of developers don’t really know if Neo4j will actually be a good match for their specific needs; here’s a solid overview on Stackoverflow discussing why to use Neo4j and the pros and cons.

此外,很多开发人员并不真正了解Neo4j是否真的能满足他们的具体需求;这里是Stackoverflow上的一份可靠的概述,讨论了为什么要使用Neo4j以及其优点和缺点。

2. Maven Dependencies

2.Maven的依赖性

Let’s start by declaring the Spring Data Neo4j dependencies in the pom.xml. The below mentioned Spring modules are also required for Spring Data Neo4j:

让我们先在pom.xml中声明Spring Data Neo4j的依赖关系。下面提到的Spring模块也是Spring Data Neo4j所需要的。

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-neo4j</artifactId>
    <version>5.0.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.neo4j</groupId>
    <artifactId>neo4j-ogm-test</artifactId>
    <version>3.1.2</version>
    <scope>test</scope>
</dependency>

These dependencies include the required modules for testing as well.

这些依赖性也包括测试所需的模块。

Note that the last dependency is scoped as ‘test’. But also note that, in a real world application development, you’re more likely to have a full Neo4J server running.

请注意,最后一个依赖关系的范围是 “测试”。但也要注意,在现实世界的应用开发中,你更可能会有一个完整的Neo4J服务器在运行。

If we want to use the embedded server, we also have to add the dependency:

如果我们想使用嵌入式服务器,我们也必须添加该依赖关系。

<dependency>
    <groupId>org.neo4j</groupId>
    <artifactId>neo4j-ogm-embedded-driver</artifactId>
    <version>3.1.2</version>
</dependency>

The spring-data-neo4j, neo4j-ogm-test and neo4j-ogm-embedded-driver dependencies are available on Maven Central.

spring-data-neo4jneo4j-ogm-testneo4j-ogm-embedded-driver依赖项可在Maven Central获得。

3. Neo4Jj Configuration

3.Neo4Jj配置

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.

Neo4j配置是非常直接的,它定义了应用程序连接到服务器的连接设置。与其他大多数Spring数据模块类似,这是一个Spring配置,可以定义为XML或Java配置。

In this tutorial, we’ll use Java-based configuration only:

在本教程中,我们将只使用基于Java的配置。

public static final String URL = 
  System.getenv("NEO4J_URL") != null ? 
  System.getenv("NEO4J_URL") : "http://neo4j:movies@localhost:7474";

@Bean
public org.neo4j.ogm.config.Configuration getConfiguration() {
    return new Builder().uri(URL).build();
}

@Bean
public SessionFactory getSessionFactory() {
    return new SessionFactory(getConfiguration(), 
      "com.baeldung.spring.data.neo4j.domain");
}

@Bean
public Neo4jTransactionManager transactionManager() {
    return new Neo4jTransactionManager(getSessionFactory());
}

As mentioned above, the config is simple and contains only two settings. First – the SessionFactory is referencing the models that we created to represent the data objects. Then, the connection properties with the server endpoints and access credentials.

如上所述,该配置很简单,只包含两个设置。首先–SessionFactory是引用我们创建的模型来表示数据对象。然后,带有服务器端点和访问证书的连接属性。

Neo4j will infer the driver class based on the protocol of the URI, in our case “http”.

Neo4j会根据URI的协议来推断驱动类,在我们的例子中是 “http”。

Please note that in this example, the connection related properties are configured directly to the server; however in a production application, these should be properly externalized and part of the standard configuration of the project.

请注意,在这个例子中,连接相关的属性是直接配置给服务器的;但是在生产应用中,这些属性应该被适当地外部化,成为项目标准配置的一部分。

4. Neo4j Repositories

4.Neo4j Repositories

Aligning with the Spring Data framework, Neo4j supports the Spring Data repository abstraction behavior. That means accessing the underlying persistent mechanism is abstracted in the inbuilt Neo4jRepository where a project can directly extend it and use the provided operations out-of-the-box.

为了与Spring Data框架保持一致,Neo4j支持Spring Data资源库的抽象行为。这意味着访问底层的持久化机制在内置的Neo4jRepository中被抽象出来,项目可以直接扩展它并使用提供的操作。

The repositories are extensible by annotated, named or derived finder methods. Support for Spring Data Neo4j Repositories are also based on Neo4jTemplate, so the underlying functionality is identical.

存储库可通过注释、命名或派生的查找方法进行扩展。对Spring Data Neo4j Repositories的支持也是基于Neo4jTemplate,所以底层功能是相同的。

4.1. Creating the MovieRepository & PersonRepository

4.1.创建MovieRepository & PersonRepository

We use two repositories in this tutorial for data persistence:

在本教程中,我们使用两个存储库进行数据持久化。

@Repository
public interface MovieRepository extends Neo4jRepository<Movie, Long> {

    Movie findByTitle(@Param("title") String title);

    @Query("MATCH (m:Movie) WHERE m.title =~ ('(?i).*'+{title}+'.*') RETURN m")
    Collection<Movie> 
      findByTitleContaining(@Param("title") String title);

    @Query("MATCH (m:Movie)<-[:ACTED_IN]-(a:Person) 
      RETURN m.title as movie, collect(a.name) as cast LIMIT {limit}")
    List<Map<String,Object>> graph(@Param("limit") int limit);
}

As you can, the repository contains some custom operations as well as the standard ones inherited from the base class.

正如你所看到的,资源库包含了一些自定义操作以及从基类继承的标准操作。

Next we have the simpler PersonRepository, which just has the standard operations:

接下来我们有更简单的PersonRepository,它只有标准操作。

@Repository
public interface PersonRepository extends Neo4jRepository <Person, Long> {
    //
}

You may have already noticed that PersonRepository is just the standard Spring Data interface. This is because, in this simple example, it is almost sufficient to use the inbuilt operations basically as our operation set is related to the Movie entity. However you can always add custom operations here which may wrap single/ multiple inbuilt operations.

你可能已经注意到,PersonRepository只是一个标准的Spring Data接口。这是因为,在这个简单的例子中,基本上使用内置的操作就足够了,因为我们的操作集与Movie实体有关。然而,你总是可以在这里添加自定义操作,这些操作可以包裹单个/多个内置的操作。

4.2. Configuring Neo4jRepositories

4.2.配置Neo4jRepositories

As the next step, we have to let Spring know the relevant repository indicating it in the Neo4jConfiguration class created in section 3:

下一步,我们必须让Spring知道相关的资源库,并在第3节创建的Neo4jConfiguration类中指明它。

@Configuration
@ComponentScan("com.baeldung.spring.data.neo4j")
@EnableNeo4jRepositories(
  basePackages = "com.baeldung.spring.data.neo4j.repository")
public class MovieDatabaseNeo4jConfiguration {
    //
}

5. The Full Data Model

5.完整的数据模型

We already started looking at the data model, so let’s now lay it all out – the full Movie, Role and Person. The Person entity references the Movie entity through the Role relationship.

我们已经开始看数据模型,所以现在让我们把它全部摆出来–完整的Movie、Role PersonPerson实体通过Role关系引用Movie实体。

@NodeEntity
public class Movie {

    @Id @GeneratedValue
    Long id;

    private String title;

    private int released;

    private String tagline;

    @Relationship(type="ACTED_IN", direction = Relationship.INCOMING)

    private List<Role> roles;

    // standard constructor, getters and setters 
}

Notice how we’ve annotated Movie with @NodeEntity to indicate that this class is directly mapped to a node in Neo4j.

请注意我们如何用@NodeEntity来注释Movie,以表明这个类直接映射到Neo4j的一个节点。

@JsonIdentityInfo(generator=JSOGGenerator.class)
@NodeEntity
public class Person {

    @Id @GeneratedValue
    Long id;

    private String name;

    private int born;

    @Relationship(type = "ACTED_IN")
    private List<Movie> movies;

    // standard constructor, getters and setters 
}

@JsonIdentityInfo(generator=JSOGGenerator.class)
@RelationshipEntity(type = "ACTED_IN")
public class Role {

    @Id @GeneratedValue
    Long id;

    private Collection<String> roles;

    @StartNode
    private Person person;

    @EndNode
    private Movie movie;

    // standard constructor, getters and setters 
}

Of course, these last couple of classes are similarly annotated and the -movies reference is linking Person to Movie class by the “ACTED_IN” relationship.

当然,这最后几个类也有类似的注释,-movies引用是通过 “ACTED_IN “关系将Person连接到Movieclass。

6. Data Access Using MovieRepository

6.使用MovieRepository的数据访问

6.1. Saving a New Movie Object

6.1.保存一个新的电影对象

Let’s save some data – first, a new Movie, then a Person and of course a Role – including all the relation data we have as well:

让我们保存一些数据–首先是一个新的电影,然后是一个人,当然还有一个角色–也包括我们拥有的所有关系数据。

Movie italianJob = new Movie();
italianJob.setTitle("The Italian Job");
italianJob.setReleased(1999);
movieRepository.save(italianJob);

Person mark = new Person();
mark.setName("Mark Wahlberg");
personRepository.save(mark);

Role charlie = new Role();
charlie.setMovie(italianJob);
charlie.setPerson(mark);
Collection<String> roleNames = new HashSet();
roleNames.add("Charlie Croker");
charlie.setRoles(roleNames);
List<Role> roles = new ArrayList();
roles.add(charlie);
italianJob.setRoles(roles);
movieRepository.save(italianJob);

6.2. Retrieving an Existing Movie Object by Title

6.2.按标题检索一个现有的电影对象

Let’s now verify the inserted movie by retrieving it using the defined title which is a custom operation:

现在让我们通过使用定义的标题检索来验证插入的电影,这是一个自定义操作。

Movie result = movieRepository.findByTitle(title);

6.3. Retrieving an Existing Movie Object by a Part of the Title

6.3.通过标题的一部分检索一个现有的电影对象

It is possible to search to search an existing movie using a part of the title:

可以用标题的一部分来搜索现有的电影。

Collection<Movie> result = movieRepository.findByTitleContaining("Italian");

6.4. Retrieving All the Movies

6.4.检索所有的电影

All the movies can be retrieve once and can be check for the correct count:

所有的电影都可以被检索一次,并可以检查正确的数量。

Collection<Movie> result = (Collection<Movie>) movieRepository.findAll();

However there are number of find methods provided with default behavior which is useful for customs requirements and not all are described here.

然而,有许多查找方法提供了默认的行为,这对海关的要求是很有用的,这里并没有全部描述。

6.5. Count the Existing Movie Objects

6.5.计算现有的电影对象

After inserting several movie objects, we can get exiting movie count:

在插入几个电影对象后,我们可以得到退出的电影数量。

long movieCount = movieRepository.count();

6.6. Deleting an Existing Movie

6.6.删除一个现有的电影

movieRepository.delete(movieRepository.findByTitle("The Italian Job"));

After deleting the inserted movie, we can search for the movie object and verify the result is null:

删除插入的电影后,我们可以搜索电影对象并验证结果为空:

assertNull(movieRepository.findByTitle("The Italian Job"));

6.7. Delete All Inserted Data

6.7.删除所有插入的数据

It is possible to delete all the elements in the database making the database empty:

可以删除数据库中的所有元素,使数据库为空。

movieRepository.deleteAll();

The result of this operation quickly removes all data from a table.

这个操作的结果是快速删除一个表中的所有数据。

7. Conclusion

7.结论

In this tutorial, we went through the basics of Spring Data Neo4j using a very simple example.

在本教程中,我们通过一个非常简单的例子,了解了Spring Data Neo4j的基础知识。

However Neo4j is capable of catering to very advanced and complex applications having a huge set of relations and networks. And Spring Data Neo4j also offers advanced features to map annotated entity classes to the Neo4j Graph Database.

然而,Neo4j能够满足拥有大量关系和网络的非常高级和复杂的应用。而Spring Data Neo4j也提供了先进的功能,可以将注释的实体类映射到Neo4j图形数据库中。

The implementation of the above code snippets and examples can be found in the GitHub project – this is an Maven based project, so it should be easy to import and run as it is.

上述代码段的实现和例子可以在GitHub项目中找到–这是一个基于Maven的项目,所以应该很容易导入并按原样运行。