Java Spring Data Neo4j – 代码示例
文中展示的所有代码均可在 spring-data-neo4j-intro-app Github 仓库中找到。
此应用程序使用了一个现成的演示数据库,其中包含 movies 数据集,包括 Person(人物)和 Movie(电影)实体以及它们之间的连接。

连接到数据库
要连接到 Neo4j,您需要凭据和连接详细信息。由于此示例使用公共数据库,因此无需进行任何更改即可连接。
连接到 Neo4j – src/main/resources/application.properties
# Neo4j config
spring.neo4j.uri=neo4j+s://demo.neo4jlabs.com
spring.neo4j.authentication.username=movies
spring.neo4j.authentication.password=movies
spring.data.neo4j.database=moviesCode language: Shell Session (shell)
领域类 (Domain classes)
领域类代表了您领域中的数据。在本例中,将包含一个 Movie 类和一个 Person 类,外加一个 Role 类来映射它们之间的关系属性。
领域类 – domainClasses/Movie.java
@Node
public class Movie {
@Id
@GeneratedValue
private Long id;
private String title;
private int released;
@Property("tagline")
private String description;
@JsonIgnoreProperties("movie")
@Relationship(type = "ACTED_IN", direction = INCOMING)
private List<Role> actors = new ArrayList<>();
@JsonIgnoreProperties({"actedIn", "directed"})
@Relationship(type = "DIRECTED", direction = INCOMING)
private List<Person> directors = new ArrayList<>();
public Movie(String title, int released, String description) {
this.title = title;
this.released = released;
this.description = description;
}
//getters and setters
}Code language: Java (java)
@JsonIgnoreProperties 注解用于避免在输出中返回循环数据。其余注解定义了 Neo4j 映射所需的实体和属性。更多信息请参阅文档的相关章节。
领域类 – domainClasses/Person.java
public class Person {
@Id
@GeneratedValue
private Long id;
private String name;
@Property("born")
private Integer birthYear;
@JsonIgnoreProperties("person")
@Relationship(type = "ACTED_IN")
private List<Movie> actedIn = new ArrayList<>();
@JsonIgnoreProperties({"actors", "directors"})
@Relationship(type = "DIRECTED")
private List<Movie> directed = new ArrayList<>();
public Person(String name, Integer birthYear) {
this.name = name;
this.birthYear = birthYear;
}
//getters and setters
}Code language: Java (java)
接下来的 Role 类用于映射一个人在电影中扮演的角色(或多个角色)这一关系属性。
领域类 – domainClasses/Role.java
@RelationshipProperties
public class Role {
@Id
@GeneratedValue
private Long id;
private List<String> roles = new ArrayList<>();
@TargetNode
@JsonIgnoreProperties({"actedIn", "directed"})
private Person person;
//getters
}Code language: Java (java)
@RelationshipProperties 定义了此类映射 Neo4j 中关系上的属性,而 @TargetNode 注解指向关系另一端的领域类。
仓库接口 (Repository interfaces)
仓库接口通常包含用于在应用程序和数据库之间检索及返回数据的方法和查询。
仓库 – repositories/MovieRepository.java
public interface MovieRepository extends Neo4jRepository<Movie, Long> {
Movie getMovieByTitle(String title);
Iterable<Movie> findMovieByTitleLike(String title);
}Code language: Java (java)
其中两个方法分别用于通过标题检索电影,以及通过类似标题的值检索电影(处理模糊搜索)。这两个方法都不需要定义查询,因为 Spring 可以通过方法名自动推导出某些查询。更多信息请查阅文档。
仓库 – repositories/PersonRepository.java
public interface PersonRepository extends Neo4jRepository<Person, Long> {
Person getPersonByName(String name);
Iterable<Person> findPersonByNameLike(String name);
@Query("MATCH (am:Movie)<-[ai:ACTED_IN]-(p:Person)-[d:DIRECTED]->(dm:Movie) " +
"RETURN p, collect(ai), collect(d), collect(am), collect(dm);")
List<Person> getPersonsWhoActAndDirect();
}Code language: Java (java)
这里有两个派生方法用于按姓名查找人物和对姓名进行模糊搜索,此外还有一个使用 @Query 注解定义查询的方法。该查询旨在寻找既担任过演员又担任过导演的人。
控制器类 (Controller classes)
控制器将定义面向用户的端点以用于检索数据。本应用程序中定义了人物和电影两个控制器。
MovieController – /controllers/MovieController.java
@RestController
@RequestMapping("/movies")
public class MovieController {
private final MovieRepository movieRepository;
public MovieController(MovieRepository movieRepository) {
this.movieRepository = movieRepository;
}
@GetMapping
public Iterable<Movie> findAll() {
return movieRepository.findAll();
}
@GetMapping("/{title}")
public Movie getMovieByTitle(@PathVariable String title) {
return movieRepository.getMovieByTitle(title);
}
@GetMapping("/search/{title}")
public Iterable<Movie> findMovieByTitleLike(@PathVariable String title) {
return movieRepository.findMovieByTitleLike(title);
}
}Code language: Java (java)
前两个注解将该类定义为 REST 控制器并设置了主端点 (/movies)。每个方法都以 @GetMapping 注解开头,将其定义为 GET 端点。最后两个方法使用路径变量将标题作为 URL 路径中的值进行传递。
PersonController – /controllers/PersonController.java
@RestController
@RequestMapping("/people")
public class PersonController {
private final PersonRepository personRepository;
public PersonController(PersonRepository personRepository) {
this.personRepository = personRepository;
}
@GetMapping
public Iterable<Person> findAllPersons() { return personRepository.findAll(); }
@GetMapping("/{name}")
public Person getPersonByName(@PathVariable String name) {
return personRepository.getPersonByName(name);
}
@GetMapping("/search/{name}")
public Iterable<Person> findPersonByNameLike(@PathVariable String name) {
return personRepository.findPersonByNameLike(name);
}
@GetMapping("/actanddirect")
public List<Person> getPersonsWhoActAndDirect() {
return personRepository.getPersonsWhoActAndDirect();
}
}Code language: Java (java)
此控制器的主端点是 /people,这些方法的格式和语法与 Movie 控制器中看到的方法类似。
运行并测试应用程序
您可以在命令行界面通过以下命令运行应用程序,或者使用您首选 IDE 中提供的某种“运行/play”按钮。
./mvnw spring-boot:runCode language: Shell Session (shell)
任何定义的端点都应该有效,您可以尝试以下几个。每个端点的示例均可在 Github 仓库的 README 中找到。
http ":8080/movies"
http ":8080/people/Carrie Fisher"
http ":8080/people/search/Bale"Code language: Shell Session (shell)


