当前位置:   article > 正文

Neo4j学习笔记(二) SpringMVC中使用Spring Data Neo4j_neo4j id 手工赋值 mvc

neo4j id 手工赋值 mvc

目录

一.pom.xml中添加spring-data-neo4j依赖

二.数据库连接配置文件neo4j.properties

三.日志打开Cypher的DEBUG信息,便于调试

四.JAVA代码

    4.1  Neo4jConfiguration.java为配置类

    4.2  Const.java为常量定义,这里列举了关系类型

    4.3  Neo4jEntity.java图实体基类,把图实体的ID属性放在基类

    4.4  RelActedInDTO.java为业务DTO根据输入输出设计自己定义

    4.5  Movie.java定义了电影节点和对应的关系

    4.6  Person.java定义了人节点和对应的关系

    4.7  RelActedIn.java定义了参演关系

    4.8  RelDirected.java定义了导演关系

    4.9  RelFollows.java定义了跟随关系

    4.10  RelReviewed.java定义了评介关系

    4.11  MovieRepository.java定义了电影为主的图数据访问方法

    4.12  PersonRepository.java定义了人为主的图数据访问方法

    4.13  MovieService.java定义了服务接口

    4.14  MovieServiceImpl.java定义了服务实现

    4.15  MovieController.java定义了控制器

五.测试

    5.1  取得指定电影的参演演员和角色

    5.2  为电影添加演员,如果电影或演员不存在会自动创建对应的节点


一.pom.xml中添加spring-data-neo4j依赖

  • 实验中使用独立的Neo4j服务器,采用bolt协议访问。如果是使用嵌入式neo4j或者使用http协议,需要添加其他依赖。
  • 5.3.4.RELEASE版本的spring-data-neo4j需要至少
         Neo4j 3.4以上
         Spring Framework 5.2.9.RELEASE以上

  1. <!-- Neo4j -->
  2. <dependency>
  3. <groupId>org.springframework.data</groupId>
  4. <artifactId>spring-data-neo4j</artifactId>
  5. <version>5.3.4.RELEASE</version>
  6. </dependency>

二.数据库连接配置文件neo4j.properties

  1. #
  2. URI=bolt://localhost:7687
  3. username=neo4j
  4. password=password
  5. #connection.pool.size=... #see Java driver doc
  6. #encryption.level=... #see Java driver doc
  7. #trust.strategy=... #see Java driver doc
  8. #trust.certificate.file=... #see Java driver doc
  9. #connection.liveness.check.timeout=... #see Java driver doc
  10. #verify.connection=... #see Java driver doc

三.日志打开Cypher的DEBUG信息,便于调试

  • SpringMVC的时候在log4j2.xml里的Loggers里添加

  1. <Logger name="org.neo4j.ogm.drivers.bolt" level="DEBUG" additivity="false">
  2. <AppenderRef ref="Console"/>
  3. </Logger>

  • Springboot的时候只需要在application.properties里添加"logging.level.org.neo4j.ogm.drivers.bolt=DEBUG"

四.JAVA代码

   实验中采用Neo4j 4.0自带的Movie Graph为数据
   代码结构如下

    4.1  Neo4jConfiguration.java为配置类

      sessionFactory和transactionManager都改成了带neo4j开头的名字,可以在同一应用中有关系型数据库访问框架时并存使用。@EnableNeo4jRepositories的注解属性需要做相应的修改。

  1. package com.study.neo4j.config;
  2. import org.neo4j.ogm.config.ClasspathConfigurationSource;
  3. import org.neo4j.ogm.config.ConfigurationSource;
  4. import org.neo4j.ogm.session.SessionFactory;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
  8. import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
  9. import org.springframework.transaction.annotation.EnableTransactionManagement;
  10. @Configuration
  11. @EnableNeo4jRepositories(sessionFactoryRef = "neo4jSessionFactory", transactionManagerRef="neo4jTransactionManager", basePackages = "com.study.neo4j.dao")
  12. @EnableTransactionManagement
  13. public class Neo4jConfiguration {
  14. @Bean
  15. public SessionFactory neo4jSessionFactory() {
  16. // with domain entity base package(s)
  17. return new SessionFactory(configuration(), "com.study.neo4j.bean");
  18. }
  19. @Bean
  20. public org.neo4j.ogm.config.Configuration configuration() {
  21. ConfigurationSource properties = new ClasspathConfigurationSource("neo4j.properties");
  22. org.neo4j.ogm.config.Configuration configuration = new org.neo4j.ogm.config.Configuration.Builder(properties).build();
  23. return configuration;
  24. }
  25. @Bean
  26. public Neo4jTransactionManager neo4jTransactionManager() {
  27. return new Neo4jTransactionManager(neo4jSessionFactory());
  28. }
  29. }

    4.2  Const.java为常量定义,这里列举了关系类型

  1. package com.study.neo4j.bean;
  2. public class Const {
  3. public static final String REL_TYPE_ACTEDIN = "ACTED_IN";
  4. public static final String REL_TYPE_DIRECTED = "DIRECTED";
  5. public static final String REL_TYPE_FOLLOWS = "FOLLOWS";
  6. public static final String REL_TYPE_PRODUCED = "PRODUCED";
  7. public static final String REL_TYPE_REVIEWED = "REVIEWED";
  8. public static final String REL_TYPE_WROTE = "WROTE";
  9. }

    4.3  Neo4jEntity.java图实体基类,把图实体的ID属性放在基类

  1. package com.study.neo4j.bean;
  2. import org.neo4j.ogm.annotation.Id;
  3. import org.neo4j.ogm.annotation.GeneratedValue;
  4. public abstract class Neo4jEntity {
  5. @Id
  6. @GeneratedValue
  7. protected Long id;
  8. public Long getId() {
  9. return id;
  10. }
  11. public void setId(Long id) {
  12. this.id = id;
  13. }
  14. }

    4.4  RelActedInDTO.java为业务DTO根据输入输出设计自己定义

  1. package com.study.neo4j.bean;
  2. import com.study.neo4j.bean.node.Movie;
  3. import com.study.neo4j.bean.node.Person;
  4. import com.study.neo4j.bean.rel.RelActedIn;
  5. public class RelActedInDTO {
  6. private RelActedIn relActedIn;
  7. private Movie movie;
  8. private Person person;
  9. public RelActedIn getRelActedIn() {
  10. return relActedIn;
  11. }
  12. public void setRelActedIn(RelActedIn relActedIn) {
  13. this.relActedIn = relActedIn;
  14. }
  15. public Movie getMovie() {
  16. return movie;
  17. }
  18. public void setMovie(Movie movie) {
  19. this.movie = movie;
  20. }
  21. public Person getPerson() {
  22. return person;
  23. }
  24. public void setPerson(Person person) {
  25. this.person = person;
  26. }
  27. }

    4.5  Movie.java定义了电影节点和对应的关系

      三个关系类型都以电影节点为结束节点

  1. package com.study.neo4j.bean.node;
  2. import java.util.List;
  3. import org.neo4j.ogm.annotation.NodeEntity;
  4. import org.neo4j.ogm.annotation.Relationship;
  5. import com.study.neo4j.bean.Const;
  6. import com.study.neo4j.bean.Neo4jEntity;
  7. import com.study.neo4j.bean.rel.RelDirected;
  8. import com.study.neo4j.bean.rel.RelReviewed;
  9. import com.study.neo4j.bean.rel.RelActedIn;
  10. @NodeEntity
  11. public class Movie extends Neo4jEntity {
  12. private String title;
  13. private String tagline;
  14. private Integer released;
  15. @Relationship(type = Const.REL_TYPE_ACTEDIN, direction=Relationship.INCOMING)
  16. private List<RelActedIn> relActedIns;
  17. @Relationship(type = Const.REL_TYPE_DIRECTED, direction=Relationship.INCOMING)
  18. private List<RelDirected> relDirecteds;
  19. @Relationship(type = Const.REL_TYPE_REVIEWED, direction=Relationship.INCOMING)
  20. private List<RelReviewed> relRevieweds;
  21. public String getTitle() {
  22. return title;
  23. }
  24. public void setTitle(String title) {
  25. this.title = title;
  26. }
  27. public String getTagline() {
  28. return tagline;
  29. }
  30. public void setTagline(String tagline) {
  31. this.tagline = tagline;
  32. }
  33. public Integer getReleased() {
  34. return released;
  35. }
  36. public void setReleased(Integer released) {
  37. this.released = released;
  38. }
  39. public List<RelActedIn> getRelActedIns() {
  40. return relActedIns;
  41. }
  42. public void setRelActedIns(List<RelActedIn> relActedIns) {
  43. this.relActedIns = relActedIns;
  44. }
  45. public List<RelDirected> getRelDirecteds() {
  46. return relDirecteds;
  47. }
  48. public void setRelDirecteds(List<RelDirected> relDirecteds) {
  49. this.relDirecteds = relDirecteds;
  50. }
  51. public List<RelReviewed> getRelRevieweds() {
  52. return relRevieweds;
  53. }
  54. public void setRelRevieweds(List<RelReviewed> relReviewed) {
  55. this.relRevieweds = relReviewed;
  56. }
  57. @Override
  58. public String toString() {
  59. return "Movie [title=" + title + ", tagline=" + tagline + ", released=" + released + ", relActedIns="
  60. + relActedIns + ", relDirecteds=" + relDirecteds + ", relReviewed=" + relRevieweds + ", id=" + id + "]";
  61. }
  62. }

    4.6  Person.java定义了人节点和对应的关系

      三个关系类型以人节点为结束节点
      relFollows和relFollowsBy定义了同一种关系类型,对于单个节点来说又分为以本人为结束节点的关系和以本人为开始节点的关系

  1. package com.study.neo4j.bean.node;
  2. import java.util.List;
  3. import org.neo4j.ogm.annotation.NodeEntity;
  4. import org.neo4j.ogm.annotation.Relationship;
  5. import com.study.neo4j.bean.Const;
  6. import com.study.neo4j.bean.Neo4jEntity;
  7. import com.study.neo4j.bean.rel.RelActedIn;
  8. import com.study.neo4j.bean.rel.RelDirected;
  9. import com.study.neo4j.bean.rel.RelFollows;
  10. import com.study.neo4j.bean.rel.RelReviewed;
  11. @NodeEntity
  12. public class Person extends Neo4jEntity {
  13. private String name;
  14. private Integer born;
  15. @Relationship(type = Const.REL_TYPE_ACTEDIN)
  16. private List<RelActedIn> relActedIns;
  17. @Relationship(type = Const.REL_TYPE_DIRECTED)
  18. private List<RelDirected> relDirecteds;
  19. @Relationship(type = Const.REL_TYPE_REVIEWED)
  20. private List<RelReviewed> relRevieweds;
  21. @Relationship(type = Const.REL_TYPE_FOLLOWS)
  22. private List<RelFollows> relFollows;
  23. @Relationship(type = Const.REL_TYPE_FOLLOWS, direction=Relationship.INCOMING)
  24. private List<RelFollows> relFollowsBy;
  25. public String getName() {
  26. return name;
  27. }
  28. public void setName(String name) {
  29. this.name = name;
  30. }
  31. public Integer getBorn() {
  32. return born;
  33. }
  34. public void setBorn(Integer born) {
  35. this.born = born;
  36. }
  37. public List<RelActedIn> getRelActedIns() {
  38. return relActedIns;
  39. }
  40. public void setRelActedIns(List<RelActedIn> relActedIns) {
  41. this.relActedIns = relActedIns;
  42. }
  43. public List<RelDirected> getRelDirecteds() {
  44. return relDirecteds;
  45. }
  46. public void setRelDirecteds(List<RelDirected> relDirecteds) {
  47. this.relDirecteds = relDirecteds;
  48. }
  49. public List<RelReviewed> getRelRevieweds() {
  50. return relRevieweds;
  51. }
  52. public void setRelRevieweds(List<RelReviewed> relRevieweds) {
  53. this.relRevieweds = relRevieweds;
  54. }
  55. public List<RelFollows> getRelFollows() {
  56. return relFollows;
  57. }
  58. public void setRelFollows(List<RelFollows> relFollows) {
  59. this.relFollows = relFollows;
  60. }
  61. public List<RelFollows> getRelFollowsBy() {
  62. return relFollowsBy;
  63. }
  64. public void setRelFollowsBy(List<RelFollows> relFollowsBy) {
  65. this.relFollowsBy = relFollowsBy;
  66. }
  67. @Override
  68. public String toString() {
  69. return "Person [name=" + name + ", born=" + born + ", relActedIns=" + relActedIns + ", relDirecteds="
  70. + relDirecteds + ", relRevieweds=" + relRevieweds + ", relFollows=" + relFollows + ", relFollowsBy="
  71. + relFollowsBy + ", id=" + id + "]";
  72. }
  73. }

    4.7  RelActedIn.java定义了参演关系

      分别使用@StartNode和@EndNode注解表示关系的开始节点和结束节点
      为了避免Json序列化时候的无限循环,使用@JsonIgnore注解取消对开始节点和结束节点的序列化,并在toString中不做开始节点和结束节点的toString

  1. package com.study.neo4j.bean.rel;
  2. import java.util.List;
  3. import org.neo4j.ogm.annotation.EndNode;
  4. import org.neo4j.ogm.annotation.Property;
  5. import org.neo4j.ogm.annotation.RelationshipEntity;
  6. import org.neo4j.ogm.annotation.StartNode;
  7. import com.fasterxml.jackson.annotation.JsonIgnore;
  8. import com.study.neo4j.bean.Const;
  9. import com.study.neo4j.bean.Neo4jEntity;
  10. import com.study.neo4j.bean.node.Movie;
  11. import com.study.neo4j.bean.node.Person;
  12. @RelationshipEntity(type = Const.REL_TYPE_ACTEDIN)
  13. public class RelActedIn extends Neo4jEntity {
  14. @Property
  15. private List<String> roles;
  16. @StartNode
  17. @JsonIgnore
  18. private Person person;
  19. @EndNode
  20. @JsonIgnore
  21. private Movie movie;
  22. public List<String> getRoles() {
  23. return roles;
  24. }
  25. public void setRoles(List<String> roles) {
  26. this.roles = roles;
  27. }
  28. public Person getPerson() {
  29. return person;
  30. }
  31. public void setPerson(Person person) {
  32. this.person = person;
  33. }
  34. public Movie getMovie() {
  35. return movie;
  36. }
  37. public void setMovie(Movie movie) {
  38. this.movie = movie;
  39. }
  40. @Override
  41. public String toString() {
  42. return "RelActedIn [roles=" + roles + ", person.id=" + person==null?null:person.getId() + ", movie.id=" + movie==null?null:movie.getId() + ", id=" + id + "]";
  43. }
  44. }

    4.8  RelDirected.java定义了导演关系

      分别使用@StartNode和@EndNode注解表示关系的开始节点和结束节点
      为了避免Json序列化时候的无限循环,使用@JsonIgnore注解取消对开始节点和结束节点的序列化,并在toString中不做开始节点和结束节点的toString

  1. package com.study.neo4j.bean.rel;
  2. import org.neo4j.ogm.annotation.EndNode;
  3. import org.neo4j.ogm.annotation.RelationshipEntity;
  4. import org.neo4j.ogm.annotation.StartNode;
  5. import com.fasterxml.jackson.annotation.JsonIgnore;
  6. import com.study.neo4j.bean.Const;
  7. import com.study.neo4j.bean.Neo4jEntity;
  8. import com.study.neo4j.bean.node.Movie;
  9. import com.study.neo4j.bean.node.Person;
  10. @RelationshipEntity(type = Const.REL_TYPE_DIRECTED)
  11. public class RelDirected extends Neo4jEntity {
  12. @StartNode
  13. @JsonIgnore
  14. private Person person;
  15. @EndNode
  16. @JsonIgnore
  17. private Movie movie;
  18. public Person getPerson() {
  19. return person;
  20. }
  21. public void setPerson(Person person) {
  22. this.person = person;
  23. }
  24. public Movie getMovie() {
  25. return movie;
  26. }
  27. public void setMovie(Movie movie) {
  28. this.movie = movie;
  29. }
  30. @Override
  31. public String toString() {
  32. return "RelActedIn [person.id=" + person==null?null:person.getId() + ", movie.id=" + movie==null?null:movie.getId() + ", id=" + id + "]";
  33. }
  34. }

    4.9  RelFollows.java定义了跟随关系

      分别使用@StartNode和@EndNode注解表示关系的开始节点和结束节点
      为了避免Json序列化时候的无限循环,使用@JsonIgnore注解取消对开始节点和结束节点的序列化,并在toString中不做开始节点和结束节点的toString

  1. package com.study.neo4j.bean.rel;
  2. import org.neo4j.ogm.annotation.EndNode;
  3. import org.neo4j.ogm.annotation.RelationshipEntity;
  4. import org.neo4j.ogm.annotation.StartNode;
  5. import com.fasterxml.jackson.annotation.JsonIgnore;
  6. import com.study.neo4j.bean.Const;
  7. import com.study.neo4j.bean.Neo4jEntity;
  8. import com.study.neo4j.bean.node.Person;
  9. @RelationshipEntity(type = Const.REL_TYPE_FOLLOWS)
  10. public class RelFollows extends Neo4jEntity {
  11. @StartNode
  12. @JsonIgnore
  13. private Person person;
  14. @EndNode
  15. @JsonIgnore
  16. private Person followPerson;
  17. public Person getPerson() {
  18. return person;
  19. }
  20. public void setPerson(Person person) {
  21. this.person = person;
  22. }
  23. public Person getFollowPerson() {
  24. return followPerson;
  25. }
  26. public void setMovie(Person followPerson) {
  27. this.followPerson = followPerson;
  28. }
  29. @Override
  30. public String toString() {
  31. return "RelActedIn [person.id=" + person==null?null:person.getId() + ", followPerson.id=" + followPerson==null?null:followPerson.getId() + ", id=" + id + "]";
  32. }
  33. }

    4.10  RelReviewed.java定义了评介关系

      分别使用@StartNode和@EndNode注解表示关系的开始节点和结束节点
      为了避免Json序列化时候的无限循环,使用@JsonIgnore注解取消对开始节点和结束节点的序列化,并在toString中不做开始节点和结束节点的toString

  1. package com.study.neo4j.bean.rel;
  2. import org.neo4j.ogm.annotation.EndNode;
  3. import org.neo4j.ogm.annotation.RelationshipEntity;
  4. import org.neo4j.ogm.annotation.StartNode;
  5. import com.fasterxml.jackson.annotation.JsonIgnore;
  6. import com.study.neo4j.bean.Const;
  7. import com.study.neo4j.bean.Neo4jEntity;
  8. import com.study.neo4j.bean.node.Movie;
  9. import com.study.neo4j.bean.node.Person;
  10. @RelationshipEntity(type = Const.REL_TYPE_REVIEWED)
  11. public class RelReviewed extends Neo4jEntity {
  12. private Integer rating;
  13. private String summary;
  14. @StartNode
  15. @JsonIgnore
  16. private Person person;
  17. @EndNode
  18. @JsonIgnore
  19. private Movie movie;
  20. public Integer getRating() {
  21. return rating;
  22. }
  23. public void setRating(Integer rating) {
  24. this.rating = rating;
  25. }
  26. public String getSummary() {
  27. return summary;
  28. }
  29. public void setSummary(String summary) {
  30. this.summary = summary;
  31. }
  32. public Person getPerson() {
  33. return person;
  34. }
  35. public void setPerson(Person person) {
  36. this.person = person;
  37. }
  38. public Movie getMovie() {
  39. return movie;
  40. }
  41. public void setMovie(Movie movie) {
  42. this.movie = movie;
  43. }
  44. @Override
  45. public String toString() {
  46. return "RelReviewed [rating=" + rating + ", summary=" + summary + ", person.id=" + person==null?null:person.getId() + ", movie.id=" + movie==null?null:movie.getId()
  47. + ", id=" + id + "]";
  48. }
  49. }

    4.11  MovieRepository.java定义了电影为主的图数据访问方法

      findByTitle为自动生成型方法,函数的查询语句会根据方法名自动生成,这个功能很有意思,后面再另起一篇记载自动生成都可以有哪些要素。查询的默认深度为1,即查询本节点以及和本节点有直接关系的节点,查询的关系类型为Movie.java中定义的关系类型。可以使用@Depth注解直接改变当前方法的查询深度,也可以使用(@Depth int depth)定义为方法的一个参数,根据传入参数决定查询深度,0为只查询本节点不查询关系,-1为无限延申。
      其他函数为自定义查询,没有深度的问题,只返回自己Cypher写的return内容。
      查询可以返回分页数据,例如getActorsThatActInMovieFromTitle。
      如果要直接返回指定关系类型,需要Cypher里return (n1)-[r]->(n2)类似的路径。

  1. package com.study.neo4j.dao;
  2. import java.util.List;
  3. import org.springframework.data.domain.Page;
  4. import org.springframework.data.domain.PageRequest;
  5. import org.springframework.data.neo4j.annotation.Depth;
  6. import org.springframework.data.neo4j.annotation.Query;
  7. import org.springframework.data.neo4j.repository.Neo4jRepository;
  8. import com.study.neo4j.bean.node.Movie;
  9. import com.study.neo4j.bean.node.Person;
  10. import com.study.neo4j.bean.rel.RelActedIn;
  11. public interface MovieRepository extends Neo4jRepository<Movie,Long> {
  12. // returns the node with id equal to idOfMovie parameter
  13. @Query("MATCH (n) WHERE id(n)=$0 RETURN n")
  14. Movie getMovieFromId(Integer idOfMovie);
  15. // returns the nodes which have a title according to the movieTitle parameter
  16. @Query("MATCH (movie:Movie {title:$0}) RETURN movie")
  17. Movie getMovieFromTitle(String movieTitle);
  18. //@Depth(value=2)
  19. Movie findByTitle(String title);
  20. // returns a Page of Person that have a ACTED_IN relationship to the movie node with the title equal to movieTitle parameter.
  21. @Query(value = "MATCH (movie:Movie {title:$0})<-[:ACTED_IN]-(actor) RETURN actor ORDER BY actor.name", countQuery= "MATCH (movie:Movie {title:$0})<-[:ACTED_IN]-(actor) RETURN count(actor)")
  22. Page<Person> getActorsThatActInMovieFromTitle(String movieTitle, PageRequest page);
  23. // returns a Slice of Person that have a ACTED_IN relationship to the movie node with the title equal to movieTitle parameter.
  24. @Query("MATCH p=(movie:Movie {title:$0})<-[relActedIn:ACTED_IN]-(actor) RETURN p")
  25. List<RelActedIn> getActorsAndRolesThatActInMovieFromTitle(String movieTitle);
  26. // returns users who directed a movie
  27. @Query("MATCH (movie:Movie {title:$0})<-[DIRECTED]-(user) RETURN user")
  28. List<Person> getUsersWhoRatedMovieFromTitle(String movieTitle);
  29. }

    4.12  PersonRepository.java定义了人为主的图数据访问方法

  1. package com.study.neo4j.dao;
  2. import org.springframework.data.neo4j.repository.Neo4jRepository;
  3. import com.study.neo4j.bean.node.Person;
  4. public interface PersonRepository extends Neo4jRepository<Person,Long> {
  5. //@Depth(value=2)
  6. Person findByName(String name);
  7. }

    4.13  MovieService.java定义了服务接口

  1. package com.study.neo4j.service;
  2. import java.util.List;
  3. import java.util.Map;
  4. import com.study.neo4j.bean.RelActedInDTO;
  5. import com.study.neo4j.bean.node.Movie;
  6. import com.study.neo4j.bean.node.Person;
  7. public interface MovieService {
  8. public Iterable<Movie> findAll();
  9. public Movie getMovie(String movieTitle);
  10. public List<Person> getActorsByMovieTitle(String movieTitle);
  11. public List<Person> getActorsAndRolesByMovieTitle(String movieTitle);
  12. public RelActedInDTO addActors(RelActedInDTO relActedInDTO);
  13. public Map<String, List<Person>> getPersonsByMovieTitle(String movieTitle);
  14. }

    4.14  MovieServiceImpl.java定义了服务实现

      @Transactional(value="neo4jTransactionManager")指定使用Neo4jConfiguration.java里定义的事务管理器。如果本应用中没有其他事务管理器可以去除括号里的内容
      Neo4jRepository.save()保存数据时,默认深度是-1,所有movie的属性、movie对应的关系、movie对应的人、人对应的关系......,会自动判断查询出来之后有没有发生变化,如果有变化,会自动更新。也可以手动指定保存时的深度,0为只保存movie的属性,不管对应的关系以及关系连接的节点,1为保存movie的属性、关系以及关系连接的节点的属性。

  1. package com.study.neo4j.service;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. import org.apache.commons.lang3.StringUtils;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.data.domain.Page;
  9. import org.springframework.data.domain.PageRequest;
  10. import org.springframework.stereotype.Service;
  11. import org.springframework.transaction.annotation.Transactional;
  12. import com.study.neo4j.bean.RelActedInDTO;
  13. import com.study.neo4j.bean.node.Movie;
  14. import com.study.neo4j.bean.node.Person;
  15. import com.study.neo4j.bean.rel.RelActedIn;
  16. import com.study.neo4j.bean.rel.RelDirected;
  17. import com.study.neo4j.bean.rel.RelReviewed;
  18. import com.study.neo4j.dao.MovieRepository;
  19. import com.study.neo4j.dao.PersonRepository;
  20. @Service("movieService")
  21. @Transactional(value="neo4jTransactionManager")
  22. public class MovieServiceImpl implements MovieService {
  23. @Autowired
  24. private MovieRepository movieRepository;
  25. @Autowired
  26. private PersonRepository personRepository;
  27. @Override
  28. public Iterable<Movie> findAll() {
  29. return movieRepository.findAll();
  30. }
  31. @Override
  32. public Movie getMovie(String movieTitle) {
  33. return movieRepository.getMovieFromTitle(movieTitle);
  34. }
  35. @Override
  36. public List<Person> getActorsByMovieTitle(String movieTitle) {
  37. PageRequest pageRequest = PageRequest.of(0, 3);
  38. Page<Person> person = movieRepository.getActorsThatActInMovieFromTitle(movieTitle, pageRequest);
  39. return person.toList();
  40. }
  41. @Override
  42. public List<Person> getActorsAndRolesByMovieTitle(String movieTitle) {
  43. List<Person> listRet = new ArrayList<Person>();
  44. List<RelActedIn> list = movieRepository.getActorsAndRolesThatActInMovieFromTitle(movieTitle);
  45. for (RelActedIn relActedIn : list) {
  46. listRet.add(relActedIn.getPerson());
  47. }
  48. return listRet;
  49. }
  50. @Override
  51. public RelActedInDTO addActors(RelActedInDTO relActedInDTO) {
  52. // 查找电影,没有就使用请求参数新建
  53. Movie movie = movieRepository.findByTitle(relActedInDTO.getMovie().getTitle());
  54. if (movie == null) {
  55. movie = relActedInDTO.getMovie();
  56. movie.setRelActedIns(new ArrayList<RelActedIn>(1));
  57. }
  58. // 查新人,没有就使用请求参数新建
  59. Person person = personRepository.findByName(relActedInDTO.getPerson().getName());
  60. if (person == null) {
  61. person = relActedInDTO.getPerson();
  62. person.setRelActedIns(new ArrayList<RelActedIn>(1));
  63. }
  64. RelActedIn relActedIn = null;
  65. // 查询是否已经参演
  66. for (RelActedIn relActedInTmp:movie.getRelActedIns()) {
  67. if (StringUtils.equals(person.getName(), relActedInTmp.getPerson().getName())) {
  68. relActedIn = relActedInTmp;
  69. break;
  70. }
  71. }
  72. if (relActedIn == null) {
  73. // 变更前没有参演,新建关系
  74. relActedIn = relActedInDTO.getRelActedIn();
  75. relActedIn.setMovie(movie);
  76. relActedIn.setPerson(person);
  77. movie.getRelActedIns().add(relActedIn);
  78. person.getRelActedIns().add(relActedIn);
  79. } else {
  80. // 改变参演角色列表
  81. relActedIn.setRoles(relActedInDTO.getRelActedIn().getRoles());
  82. }
  83. movieRepository.save(movie);
  84. // 设置返回值
  85. RelActedInDTO retRelActedInDTO = new RelActedInDTO();
  86. retRelActedInDTO.setMovie(movie);
  87. retRelActedInDTO.setPerson(person);
  88. retRelActedInDTO.setRelActedIn(relActedIn);
  89. return retRelActedInDTO;
  90. }
  91. @Override
  92. public Map<String, List<Person>> getPersonsByMovieTitle(String movieTitle) {
  93. Movie movie = movieRepository.findByTitle(movieTitle);
  94. Map<String, List<Person>> retMap = new HashMap<String, List<Person>>();
  95. // 取得参演人员
  96. List<Person> list = new ArrayList<Person>();
  97. for (RelActedIn relActed : movie.getRelActedIns()) {
  98. list.add(relActed.getPerson());
  99. }
  100. retMap.put("actedIns", list);
  101. // 取得导演人员
  102. list = new ArrayList<Person>();
  103. for (RelDirected relDirected : movie.getRelDirecteds()) {
  104. list.add(relDirected.getPerson());
  105. }
  106. retMap.put("directeds", list);
  107. // 取得评介人员
  108. list = new ArrayList<Person>();
  109. for (RelReviewed relReviewed : movie.getRelRevieweds()) {
  110. list.add(relReviewed.getPerson());
  111. }
  112. retMap.put("revieweds", list);
  113. return retMap;
  114. }
  115. }

    4.15  MovieController.java定义了控制器

  1. package com.study.neo4j.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.web.bind.annotation.CrossOrigin;
  4. import org.springframework.web.bind.annotation.RequestBody;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RequestMethod;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import com.mvc.base.controller.BaseController;
  9. import com.study.neo4j.bean.RelActedInDTO;
  10. import com.study.neo4j.bean.node.Movie;
  11. import com.study.neo4j.service.MovieService;
  12. import com.util.RestResponse;
  13. @CrossOrigin(origins = "*", allowCredentials = "true", allowedHeaders = "*", methods = {RequestMethod.GET, RequestMethod.POST})
  14. @RestController
  15. @RequestMapping("/movie")
  16. public class MovieController extends BaseController {
  17. @Autowired
  18. private MovieService movieService;
  19. /**
  20. * 取得所有电影
  21. *
  22. * @return RestResponse
  23. */
  24. @RequestMapping(value = "/findAll")
  25. public RestResponse findAll() {
  26. return RestResponse.success(movieService.findAll());
  27. }
  28. /**
  29. * 通过电影名取得电影
  30. *
  31. * @return RestResponse
  32. */
  33. @RequestMapping(value = "/getMovieByTitle")
  34. public RestResponse getMovieByTitle(@RequestBody Movie movie) {
  35. return RestResponse.success(movieService.getMovie(movie.getTitle()));
  36. }
  37. /**
  38. * 通过电影名取得演员
  39. *
  40. * @return RestResponse
  41. */
  42. @RequestMapping(value = "/getActorsByMovieTitle")
  43. public RestResponse getActorsByMovieTitle(@RequestBody Movie movie) {
  44. return RestResponse.success(movieService.getActorsByMovieTitle(movie.getTitle()));
  45. }
  46. /**
  47. * 通过电影名取得演员(包含参演角色)
  48. *
  49. * @return RestResponse
  50. */
  51. @RequestMapping(value = "/getActorsAndRolesByMovieTitle")
  52. public RestResponse getActorsAndRolesByMovieTitle(@RequestBody Movie movie) {
  53. return RestResponse.success(movieService.getActorsAndRolesByMovieTitle(movie.getTitle()));
  54. }
  55. /**
  56. * 通过电影名取得相关人员和关系
  57. *
  58. * @return RestResponse
  59. */
  60. @RequestMapping(value = "/getPersonsByMovieTitle")
  61. public RestResponse getPersonsByMovieTitle(@RequestBody Movie movie) {
  62. return RestResponse.success(movieService.getPersonsByMovieTitle(movie.getTitle()));
  63. }
  64. /**
  65. * 为电影添加演员
  66. *
  67. * @return RestResponse
  68. */
  69. @RequestMapping(value = "/addActors")
  70. public RestResponse addActors(@RequestBody RelActedInDTO relActedInDTO) {
  71. return RestResponse.success(movieService.addActors(relActedInDTO));
  72. }
  73. }

五.测试

    5.1  取得指定电影的参演演员和角色

        请求地址  /movie/getActorsAndRolesByMovieTitle
        请求Json内容:

{"title":"The Matrix"}

        返回内容:

  1. {
  2. "code": 0,
  3. "count": 0,
  4. "data": [
  5. {
  6. "id": 8,
  7. "name": "Emil Eifrem",
  8. "born": 1978,
  9. "relActedIns": [
  10. {
  11. "id": 7,
  12. "roles": [
  13. "Emil"
  14. ]
  15. }
  16. ],
  17. "relDirecteds": null,
  18. "relRevieweds": null,
  19. "relFollows": null,
  20. "relFollowsBy": null
  21. },
  22. {
  23. "id": 3,
  24. "name": "Laurence Fishburne",
  25. "born": 1961,
  26. "relActedIns": [
  27. {
  28. "id": 2,
  29. "roles": [
  30. "Morpheus"
  31. ]
  32. }
  33. ],
  34. "relDirecteds": null,
  35. "relRevieweds": null,
  36. "relFollows": null,
  37. "relFollowsBy": null
  38. },
  39. {
  40. "id": 4,
  41. "name": "Hugo Weaving",
  42. "born": 1960,
  43. "relActedIns": [
  44. {
  45. "id": 3,
  46. "roles": [
  47. "Agent Smith"
  48. ]
  49. }
  50. ],
  51. "relDirecteds": null,
  52. "relRevieweds": null,
  53. "relFollows": null,
  54. "relFollowsBy": null
  55. },
  56. {
  57. "id": 2,
  58. "name": "Carrie-Anne Moss",
  59. "born": 1967,
  60. "relActedIns": [
  61. {
  62. "id": 1,
  63. "roles": [
  64. "Trinity"
  65. ]
  66. }
  67. ],
  68. "relDirecteds": null,
  69. "relRevieweds": null,
  70. "relFollows": null,
  71. "relFollowsBy": null
  72. },
  73. {
  74. "id": 1,
  75. "name": "Keanu Reeves",
  76. "born": 1964,
  77. "relActedIns": [
  78. {
  79. "id": 0,
  80. "roles": [
  81. "Neo"
  82. ]
  83. }
  84. ],
  85. "relDirecteds": null,
  86. "relRevieweds": null,
  87. "relFollows": null,
  88. "relFollowsBy": null
  89. }
  90. ],
  91. "msg": "操作成功"
  92. }

    5.2  为电影添加演员,如果电影或演员不存在会自动创建对应的节点

        请求地址  /movie/addActors
        请求Json内容:

  1. {
  2. "movie": {
  3. "title": "这是一个新电影",
  4. "tagline": "这是电影宣传词",
  5. "released": 2020
  6. },
  7. "person": {
  8. "name": "李四",
  9. "born": 1986
  10. },
  11. "relActedIn": {
  12. "roles": [
  13. "大铃铛",
  14. "路人乙",
  15. "大坏蛋"
  16. ]
  17. }
  18. }

        返回内容:

  1. {
  2. "code": 0,
  3. "count": 0,
  4. "data": {
  5. "relActedIn": {
  6. "id": 254,
  7. "roles": [
  8. "大铃铛",
  9. "路人乙",
  10. "大坏蛋"
  11. ]
  12. },
  13. "movie": {
  14. "id": 172,
  15. "title": "这是一个新电影",
  16. "tagline": "这是电影宣传词",
  17. "released": 2020,
  18. "relActedIns": [
  19. {
  20. "id": 257,
  21. "roles": [
  22. "路人丙2"
  23. ]
  24. },
  25. {
  26. "id": 256,
  27. "roles": [
  28. "路人丙"
  29. ]
  30. },
  31. {
  32. "id": 253,
  33. "roles": [
  34. "小铃铛",
  35. "路人甲"
  36. ]
  37. },
  38. {
  39. "id": 254,
  40. "roles": [
  41. "大铃铛",
  42. "路人乙",
  43. "大坏蛋"
  44. ]
  45. }
  46. ],
  47. "relDirecteds": null,
  48. "relRevieweds": null
  49. },
  50. "person": {
  51. "id": 174,
  52. "name": "李四",
  53. "born": 1986,
  54. "relActedIns": [
  55. {
  56. "id": 254,
  57. "roles": [
  58. "大铃铛",
  59. "路人乙",
  60. "大坏蛋"
  61. ]
  62. }
  63. ],
  64. "relDirecteds": null,
  65. "relRevieweds": null,
  66. "relFollows": null,
  67. "relFollowsBy": null
  68. }
  69. },
  70. "msg": "操作成功"
  71. }

        多次更改后的图:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/727757
推荐阅读
相关标签
  

闽ICP备14008679号