Neo4j学习笔记(二) SpringMVC中使用Spring Data Neo4j

目录

一.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以上

        
        
            org.springframework.data
            spring-data-neo4j
            5.3.4.RELEASE
        

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

#
URI=bolt://localhost:7687
username=neo4j
password=password
#connection.pool.size=... #see Java driver doc
#encryption.level=... #see Java driver doc
#trust.strategy=... #see Java driver doc
#trust.certificate.file=... #see Java driver doc
#connection.liveness.check.timeout=... #see Java driver doc
#verify.connection=... #see Java driver doc

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

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

        
            
        

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

四.JAVA代码

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

Neo4j学习笔记(二) SpringMVC中使用Spring Data Neo4j_第1张图片

    4.1  Neo4jConfiguration.java为配置类

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

package com.study.neo4j.config;

import org.neo4j.ogm.config.ClasspathConfigurationSource;
import org.neo4j.ogm.config.ConfigurationSource;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableNeo4jRepositories(sessionFactoryRef = "neo4jSessionFactory", transactionManagerRef="neo4jTransactionManager", basePackages = "com.study.neo4j.dao")
@EnableTransactionManagement
public class Neo4jConfiguration {
	@Bean
    public SessionFactory neo4jSessionFactory() {
        // with domain entity base package(s)
        return new SessionFactory(configuration(), "com.study.neo4j.bean");
    }

	@Bean
    public org.neo4j.ogm.config.Configuration configuration() {
        ConfigurationSource properties = new ClasspathConfigurationSource("neo4j.properties");
        org.neo4j.ogm.config.Configuration configuration = new org.neo4j.ogm.config.Configuration.Builder(properties).build();
        return configuration;
    }

	@Bean
    public Neo4jTransactionManager neo4jTransactionManager() {
        return new Neo4jTransactionManager(neo4jSessionFactory());
    }
}

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

package com.study.neo4j.bean;

public class Const {
	public static final String REL_TYPE_ACTEDIN = "ACTED_IN";
	public static final String REL_TYPE_DIRECTED = "DIRECTED";
	public static final String REL_TYPE_FOLLOWS = "FOLLOWS";
	public static final String REL_TYPE_PRODUCED = "PRODUCED";
	public static final String REL_TYPE_REVIEWED = "REVIEWED";
	public static final String REL_TYPE_WROTE = "WROTE";
}

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

package com.study.neo4j.bean;

import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.GeneratedValue;

public abstract class Neo4jEntity {
	@Id
	@GeneratedValue
	protected Long id;

	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
}

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

package com.study.neo4j.bean;

import com.study.neo4j.bean.node.Movie;
import com.study.neo4j.bean.node.Person;
import com.study.neo4j.bean.rel.RelActedIn;

public class RelActedInDTO {
	private RelActedIn relActedIn;
	private Movie movie;
	private Person person;
	public RelActedIn getRelActedIn() {
		return relActedIn;
	}
	public void setRelActedIn(RelActedIn relActedIn) {
		this.relActedIn = relActedIn;
	}
	public Movie getMovie() {
		return movie;
	}
	public void setMovie(Movie movie) {
		this.movie = movie;
	}
	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
}

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

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

package com.study.neo4j.bean.node;

import java.util.List;

import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;

import com.study.neo4j.bean.Const;
import com.study.neo4j.bean.Neo4jEntity;
import com.study.neo4j.bean.rel.RelDirected;
import com.study.neo4j.bean.rel.RelReviewed;
import com.study.neo4j.bean.rel.RelActedIn;

@NodeEntity
public class Movie extends Neo4jEntity {

    private String title;
    private String tagline;
    private Integer released;
    @Relationship(type = Const.REL_TYPE_ACTEDIN, direction=Relationship.INCOMING)
    private List relActedIns;
    @Relationship(type = Const.REL_TYPE_DIRECTED, direction=Relationship.INCOMING)
    private List relDirecteds;
    @Relationship(type = Const.REL_TYPE_REVIEWED, direction=Relationship.INCOMING)
    private List relRevieweds;

	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getTagline() {
		return tagline;
	}
	public void setTagline(String tagline) {
		this.tagline = tagline;
	}
	public Integer getReleased() {
		return released;
	}
	public void setReleased(Integer released) {
		this.released = released;
	}
	public List getRelActedIns() {
		return relActedIns;
	}
	public void setRelActedIns(List relActedIns) {
		this.relActedIns = relActedIns;
	}

	public List getRelDirecteds() {
		return relDirecteds;
	}
	public void setRelDirecteds(List relDirecteds) {
		this.relDirecteds = relDirecteds;
	}
	public List getRelRevieweds() {
		return relRevieweds;
	}
	public void setRelRevieweds(List relReviewed) {
		this.relRevieweds = relReviewed;
	}
	@Override
	public String toString() {
		return "Movie [title=" + title + ", tagline=" + tagline + ", released=" + released + ", relActedIns="
				+ relActedIns + ", relDirecteds=" + relDirecteds + ", relReviewed=" + relRevieweds + ", id=" + id + "]";
	}

}

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

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

package com.study.neo4j.bean.node;

import java.util.List;

import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;

import com.study.neo4j.bean.Const;
import com.study.neo4j.bean.Neo4jEntity;
import com.study.neo4j.bean.rel.RelActedIn;
import com.study.neo4j.bean.rel.RelDirected;
import com.study.neo4j.bean.rel.RelFollows;
import com.study.neo4j.bean.rel.RelReviewed;

@NodeEntity
public class Person extends Neo4jEntity {
    private String name;
    private Integer born;
    @Relationship(type = Const.REL_TYPE_ACTEDIN)
    private List relActedIns;
    @Relationship(type = Const.REL_TYPE_DIRECTED)
    private List relDirecteds;
    @Relationship(type = Const.REL_TYPE_REVIEWED)
    private List relRevieweds;
    @Relationship(type = Const.REL_TYPE_FOLLOWS)
    private List relFollows;
    @Relationship(type = Const.REL_TYPE_FOLLOWS, direction=Relationship.INCOMING)
    private List relFollowsBy;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getBorn() {
		return born;
	}
	public void setBorn(Integer born) {
		this.born = born;
	}
	public List getRelActedIns() {
		return relActedIns;
	}
	public void setRelActedIns(List relActedIns) {
		this.relActedIns = relActedIns;
	}
	public List getRelDirecteds() {
		return relDirecteds;
	}
	public void setRelDirecteds(List relDirecteds) {
		this.relDirecteds = relDirecteds;
	}
	public List getRelRevieweds() {
		return relRevieweds;
	}
	public void setRelRevieweds(List relRevieweds) {
		this.relRevieweds = relRevieweds;
	}
	public List getRelFollows() {
		return relFollows;
	}
	public void setRelFollows(List relFollows) {
		this.relFollows = relFollows;
	}
	public List getRelFollowsBy() {
		return relFollowsBy;
	}
	public void setRelFollowsBy(List relFollowsBy) {
		this.relFollowsBy = relFollowsBy;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", born=" + born + ", relActedIns=" + relActedIns + ", relDirecteds="
				+ relDirecteds + ", relRevieweds=" + relRevieweds + ", relFollows=" + relFollows + ", relFollowsBy="
				+ relFollowsBy + ", id=" + id + "]";
	}
}

    4.7  RelActedIn.java定义了参演关系

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

package com.study.neo4j.bean.rel;

import java.util.List;

import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.Property;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.study.neo4j.bean.Const;
import com.study.neo4j.bean.Neo4jEntity;
import com.study.neo4j.bean.node.Movie;
import com.study.neo4j.bean.node.Person;

@RelationshipEntity(type = Const.REL_TYPE_ACTEDIN)
public class RelActedIn extends Neo4jEntity {
	@Property
	private List roles;

	@StartNode
	@JsonIgnore
	private Person person;
	@EndNode
	@JsonIgnore
	private Movie movie;

	public List getRoles() {
		return roles;
	}
	public void setRoles(List roles) {
		this.roles = roles;
	}
	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	public Movie getMovie() {
		return movie;
	}
	public void setMovie(Movie movie) {
		this.movie = movie;
	}
	@Override
	public String toString() {
		return "RelActedIn [roles=" + roles + ", person.id=" + person==null?null:person.getId() + ", movie.id=" + movie==null?null:movie.getId() + ", id=" + id + "]";
	}
}

    4.8  RelDirected.java定义了导演关系

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

package com.study.neo4j.bean.rel;

import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.study.neo4j.bean.Const;
import com.study.neo4j.bean.Neo4jEntity;
import com.study.neo4j.bean.node.Movie;
import com.study.neo4j.bean.node.Person;

@RelationshipEntity(type = Const.REL_TYPE_DIRECTED)
public class RelDirected extends Neo4jEntity {

	@StartNode
	@JsonIgnore
	private Person person;
	@EndNode
	@JsonIgnore
	private Movie movie;

	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	public Movie getMovie() {
		return movie;
	}
	public void setMovie(Movie movie) {
		this.movie = movie;
	}
	@Override
	public String toString() {
		return "RelActedIn [person.id=" + person==null?null:person.getId() + ", movie.id=" + movie==null?null:movie.getId() + ", id=" + id + "]";
	}
}

    4.9  RelFollows.java定义了跟随关系

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

package com.study.neo4j.bean.rel;

import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.study.neo4j.bean.Const;
import com.study.neo4j.bean.Neo4jEntity;
import com.study.neo4j.bean.node.Person;

@RelationshipEntity(type = Const.REL_TYPE_FOLLOWS)
public class RelFollows extends Neo4jEntity {

	@StartNode
	@JsonIgnore
	private Person person;
	@EndNode
	@JsonIgnore
	private Person followPerson;

	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	public Person getFollowPerson() {
		return followPerson;
	}
	public void setMovie(Person followPerson) {
		this.followPerson = followPerson;
	}
	@Override
	public String toString() {
		return "RelActedIn [person.id=" + person==null?null:person.getId() + ", followPerson.id=" + followPerson==null?null:followPerson.getId() + ", id=" + id + "]";
	}
}

    4.10  RelReviewed.java定义了评介关系

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

package com.study.neo4j.bean.rel;

import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.study.neo4j.bean.Const;
import com.study.neo4j.bean.Neo4jEntity;
import com.study.neo4j.bean.node.Movie;
import com.study.neo4j.bean.node.Person;

@RelationshipEntity(type = Const.REL_TYPE_REVIEWED)
public class RelReviewed extends Neo4jEntity {

	private Integer rating;
	private String summary;

	@StartNode
	@JsonIgnore
	private Person person;
	@EndNode
	@JsonIgnore
	private Movie movie;

	public Integer getRating() {
		return rating;
	}
	public void setRating(Integer rating) {
		this.rating = rating;
	}
	public String getSummary() {
		return summary;
	}
	public void setSummary(String summary) {
		this.summary = summary;
	}
	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	public Movie getMovie() {
		return movie;
	}
	public void setMovie(Movie movie) {
		this.movie = movie;
	}
	@Override
	public String toString() {
		return "RelReviewed [rating=" + rating + ", summary=" + summary + ", person.id=" + person==null?null:person.getId() + ", movie.id=" + movie==null?null:movie.getId()
				+ ", id=" + id + "]";
	}
}

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

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

package com.study.neo4j.dao;

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.neo4j.annotation.Depth;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;

import com.study.neo4j.bean.node.Movie;
import com.study.neo4j.bean.node.Person;
import com.study.neo4j.bean.rel.RelActedIn;

public interface MovieRepository extends Neo4jRepository {
    // returns the node with id equal to idOfMovie parameter
    @Query("MATCH (n) WHERE id(n)=$0 RETURN n")
    Movie getMovieFromId(Integer idOfMovie);

    // returns the nodes which have a title according to the movieTitle parameter
    @Query("MATCH (movie:Movie {title:$0}) RETURN movie")
    Movie getMovieFromTitle(String movieTitle);

    //@Depth(value=2)
    Movie findByTitle(String title);

    // returns a Page of Person that have a ACTED_IN relationship to the movie node with the title equal to movieTitle parameter.
    @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)")
    Page getActorsThatActInMovieFromTitle(String movieTitle, PageRequest page);

    // returns a Slice of Person that have a ACTED_IN relationship to the movie node with the title equal to movieTitle parameter.
    @Query("MATCH p=(movie:Movie {title:$0})<-[relActedIn:ACTED_IN]-(actor) RETURN p")
    List getActorsAndRolesThatActInMovieFromTitle(String movieTitle);

    // returns users who directed a movie
    @Query("MATCH (movie:Movie {title:$0})<-[DIRECTED]-(user) RETURN user")
    List getUsersWhoRatedMovieFromTitle(String movieTitle);
}

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

package com.study.neo4j.dao;

import org.springframework.data.neo4j.repository.Neo4jRepository;

import com.study.neo4j.bean.node.Person;

public interface PersonRepository extends Neo4jRepository {
    //@Depth(value=2)
	Person findByName(String name);
}

    4.13  MovieService.java定义了服务接口

package com.study.neo4j.service;

import java.util.List;
import java.util.Map;

import com.study.neo4j.bean.RelActedInDTO;
import com.study.neo4j.bean.node.Movie;
import com.study.neo4j.bean.node.Person;

public interface MovieService {
    public Iterable findAll();
    public Movie getMovie(String movieTitle);
	public List getActorsByMovieTitle(String movieTitle);
	public List getActorsAndRolesByMovieTitle(String movieTitle);
	public RelActedInDTO addActors(RelActedInDTO relActedInDTO);
	public Map> getPersonsByMovieTitle(String movieTitle);
}

    4.14  MovieServiceImpl.java定义了服务实现

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

package com.study.neo4j.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.study.neo4j.bean.RelActedInDTO;
import com.study.neo4j.bean.node.Movie;
import com.study.neo4j.bean.node.Person;
import com.study.neo4j.bean.rel.RelActedIn;
import com.study.neo4j.bean.rel.RelDirected;
import com.study.neo4j.bean.rel.RelReviewed;
import com.study.neo4j.dao.MovieRepository;
import com.study.neo4j.dao.PersonRepository;

@Service("movieService")
@Transactional(value="neo4jTransactionManager")
public class MovieServiceImpl implements MovieService {

	@Autowired
	private MovieRepository movieRepository;
	@Autowired
	private PersonRepository personRepository;

	@Override
	public Iterable findAll() {
		return movieRepository.findAll();
	}

	@Override
	public Movie getMovie(String movieTitle) {
		return movieRepository.getMovieFromTitle(movieTitle);
	}

	@Override
	public List getActorsByMovieTitle(String movieTitle) {
		PageRequest pageRequest = PageRequest.of(0, 3);
		Page person = movieRepository.getActorsThatActInMovieFromTitle(movieTitle, pageRequest);
		return person.toList();
	}

	@Override
	public List getActorsAndRolesByMovieTitle(String movieTitle) {
		List listRet = new ArrayList();
		List list = movieRepository.getActorsAndRolesThatActInMovieFromTitle(movieTitle);
		for (RelActedIn relActedIn : list) {
			listRet.add(relActedIn.getPerson());
		}
		return listRet;
	}

	@Override
	public RelActedInDTO addActors(RelActedInDTO relActedInDTO) {
		// 查找电影,没有就使用请求参数新建
		Movie movie = movieRepository.findByTitle(relActedInDTO.getMovie().getTitle());
		if (movie == null) {
			movie = relActedInDTO.getMovie();
			movie.setRelActedIns(new ArrayList(1));
		}
		// 查新人,没有就使用请求参数新建
		Person person = personRepository.findByName(relActedInDTO.getPerson().getName());
		if (person == null) {
			person = relActedInDTO.getPerson();
			person.setRelActedIns(new ArrayList(1));
		}
		RelActedIn relActedIn = null;
		// 查询是否已经参演
		for (RelActedIn relActedInTmp:movie.getRelActedIns()) {
			if (StringUtils.equals(person.getName(), relActedInTmp.getPerson().getName())) {
				relActedIn = relActedInTmp;
				break;
			}
		}
		if (relActedIn == null) {
			// 变更前没有参演,新建关系
			relActedIn = relActedInDTO.getRelActedIn();
			relActedIn.setMovie(movie);
			relActedIn.setPerson(person);
			movie.getRelActedIns().add(relActedIn);
			person.getRelActedIns().add(relActedIn);
		} else {
			// 改变参演角色列表
			relActedIn.setRoles(relActedInDTO.getRelActedIn().getRoles());
		}
		movieRepository.save(movie);
		// 设置返回值
		RelActedInDTO retRelActedInDTO = new RelActedInDTO();
		retRelActedInDTO.setMovie(movie);
		retRelActedInDTO.setPerson(person);
		retRelActedInDTO.setRelActedIn(relActedIn);
		return retRelActedInDTO;
	}

	@Override
	public Map> getPersonsByMovieTitle(String movieTitle) {
		Movie movie = movieRepository.findByTitle(movieTitle);
		Map> retMap = new HashMap>();
		// 取得参演人员
		List list = new ArrayList();
		for (RelActedIn relActed : movie.getRelActedIns()) {
			list.add(relActed.getPerson());
		}
		retMap.put("actedIns", list);
		// 取得导演人员
		list = new ArrayList();
		for (RelDirected relDirected : movie.getRelDirecteds()) {
			list.add(relDirected.getPerson());
		}
		retMap.put("directeds", list);
		// 取得评介人员
		list = new ArrayList();
		for (RelReviewed relReviewed : movie.getRelRevieweds()) {
			list.add(relReviewed.getPerson());
		}
		retMap.put("revieweds", list);
		return retMap;
	}

}

    4.15  MovieController.java定义了控制器

package com.study.neo4j.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.mvc.base.controller.BaseController;
import com.study.neo4j.bean.RelActedInDTO;
import com.study.neo4j.bean.node.Movie;
import com.study.neo4j.service.MovieService;
import com.util.RestResponse;

@CrossOrigin(origins = "*", allowCredentials = "true", allowedHeaders = "*", methods = {RequestMethod.GET, RequestMethod.POST})
@RestController
@RequestMapping("/movie")
public class MovieController extends BaseController {
    @Autowired
    private MovieService movieService;

    /**
     * 取得所有电影
     *
     * @return RestResponse
     */
    @RequestMapping(value = "/findAll")
    public RestResponse findAll() {
        return RestResponse.success(movieService.findAll());
    }

    /**
     * 通过电影名取得电影
     *
     * @return RestResponse
     */
    @RequestMapping(value = "/getMovieByTitle")
    public RestResponse getMovieByTitle(@RequestBody Movie movie) {
        return RestResponse.success(movieService.getMovie(movie.getTitle()));
    }

    /**
     * 通过电影名取得演员
     *
     * @return RestResponse
     */
    @RequestMapping(value = "/getActorsByMovieTitle")
    public RestResponse getActorsByMovieTitle(@RequestBody Movie movie) {
        return RestResponse.success(movieService.getActorsByMovieTitle(movie.getTitle()));
    }

    /**
     * 通过电影名取得演员(包含参演角色)
     *
     * @return RestResponse
     */
    @RequestMapping(value = "/getActorsAndRolesByMovieTitle")
    public RestResponse getActorsAndRolesByMovieTitle(@RequestBody Movie movie) {
        return RestResponse.success(movieService.getActorsAndRolesByMovieTitle(movie.getTitle()));
    }

    /**
     * 通过电影名取得相关人员和关系
     *
     * @return RestResponse
     */
    @RequestMapping(value = "/getPersonsByMovieTitle")
    public RestResponse getPersonsByMovieTitle(@RequestBody Movie movie) {
        return RestResponse.success(movieService.getPersonsByMovieTitle(movie.getTitle()));
    }

    /**
     * 为电影添加演员
     *
     * @return RestResponse
     */
    @RequestMapping(value = "/addActors")
    public RestResponse addActors(@RequestBody RelActedInDTO relActedInDTO) {
        return RestResponse.success(movieService.addActors(relActedInDTO));
    }
}

五.测试

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

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

{"title":"The Matrix"}

        返回内容:

{
    "code": 0,
    "count": 0,
    "data": [
        {
            "id": 8,
            "name": "Emil Eifrem",
            "born": 1978,
            "relActedIns": [
                {
                    "id": 7,
                    "roles": [
                        "Emil"
                    ]
                }
            ],
            "relDirecteds": null,
            "relRevieweds": null,
            "relFollows": null,
            "relFollowsBy": null
        },
        {
            "id": 3,
            "name": "Laurence Fishburne",
            "born": 1961,
            "relActedIns": [
                {
                    "id": 2,
                    "roles": [
                        "Morpheus"
                    ]
                }
            ],
            "relDirecteds": null,
            "relRevieweds": null,
            "relFollows": null,
            "relFollowsBy": null
        },
        {
            "id": 4,
            "name": "Hugo Weaving",
            "born": 1960,
            "relActedIns": [
                {
                    "id": 3,
                    "roles": [
                        "Agent Smith"
                    ]
                }
            ],
            "relDirecteds": null,
            "relRevieweds": null,
            "relFollows": null,
            "relFollowsBy": null
        },
        {
            "id": 2,
            "name": "Carrie-Anne Moss",
            "born": 1967,
            "relActedIns": [
                {
                    "id": 1,
                    "roles": [
                        "Trinity"
                    ]
                }
            ],
            "relDirecteds": null,
            "relRevieweds": null,
            "relFollows": null,
            "relFollowsBy": null
        },
        {
            "id": 1,
            "name": "Keanu Reeves",
            "born": 1964,
            "relActedIns": [
                {
                    "id": 0,
                    "roles": [
                        "Neo"
                    ]
                }
            ],
            "relDirecteds": null,
            "relRevieweds": null,
            "relFollows": null,
            "relFollowsBy": null
        }
    ],
    "msg": "操作成功"
}

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

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

{
    "movie": {
        "title": "这是一个新电影",
        "tagline": "这是电影宣传词",
        "released": 2020
    },
    "person": {
        "name": "李四",
        "born": 1986
    },
    "relActedIn": {
        "roles": [
            "大铃铛",
            "路人乙",
            "大坏蛋"
        ]
    }
}

        返回内容:

{
    "code": 0,
    "count": 0,
    "data": {
        "relActedIn": {
            "id": 254,
            "roles": [
                "大铃铛",
                "路人乙",
                "大坏蛋"
            ]
        },
        "movie": {
            "id": 172,
            "title": "这是一个新电影",
            "tagline": "这是电影宣传词",
            "released": 2020,
            "relActedIns": [
                {
                    "id": 257,
                    "roles": [
                        "路人丙2"
                    ]
                },
                {
                    "id": 256,
                    "roles": [
                        "路人丙"
                    ]
                },
                {
                    "id": 253,
                    "roles": [
                        "小铃铛",
                        "路人甲"
                    ]
                },
                {
                    "id": 254,
                    "roles": [
                        "大铃铛",
                        "路人乙",
                        "大坏蛋"
                    ]
                }
            ],
            "relDirecteds": null,
            "relRevieweds": null
        },
        "person": {
            "id": 174,
            "name": "李四",
            "born": 1986,
            "relActedIns": [
                {
                    "id": 254,
                    "roles": [
                        "大铃铛",
                        "路人乙",
                        "大坏蛋"
                    ]
                }
            ],
            "relDirecteds": null,
            "relRevieweds": null,
            "relFollows": null,
            "relFollowsBy": null
        }
    },
    "msg": "操作成功"
}

        多次更改后的图:

Neo4j学习笔记(二) SpringMVC中使用Spring Data Neo4j_第2张图片

你可能感兴趣的:(neo4j,Spring,Data,Neo4j,JAVA,neo4j,SpringDataNeo4j)