Neo4j+SpringBoot实现节点以及关系的增删改查(Spring Data Neo4j)

序号:04

  公司让学习一下Neo4j在SpringBoot框架下的使用,我知道有个Spring DATA Neo4J,在网上找了很多教程,有些地方让我困惑了很久,所以记下来希望能给后面学习的伙伴一些帮助。

先上效果图:

一、开发环境

IDE:idea

JDK:1.8

先搭建一个普通的SpringBoot项目,然后导入依赖。

pom.xml如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.example</groupId>
<artifactId>neo4jdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>neo4jdemo</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--Neo4j相关-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-core</artifactId>
<version>3.2.14</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>5.3.2.RELEASE</version>
</dependency>
<!--Json处理 @JsonIdentityInfo(generator= JSOGGenerator.class)用到-->
<dependency>
<groupId>com.voodoodyne.jackson.jsog</groupId>
<artifactId>jackson-jsog</artifactId>
<version>1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

yml配置:

1
2
3
4
5
6
spring:
data:
neo4j:
uri: bolt://localhost:7687
username: neo4j
password: cldev

二、代码部分

目录结构:

  为了简单,本项目节点只设置一种类型(User),实现的关系的某一个User知道另一User,关系(Know)。

首先编写User节点类(UserNode .java):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

package com.example.neo4jdemo.entity.node;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.voodoodyne.jackson.jsog.JSOGGenerator;
import org.neo4j.ogm.annotation.*;
import java.util.HashSet;
import java.util.Set;

@JsonIdentityInfo(generator= JSOGGenerator.class)
@NodeEntity(label = "User")
public class UserNode {

@Id
@GeneratedValue
private Long nodeId;

@Property(name = "name")
private String name;

@Property(name = "age")
private int age;

@Property(name = "sex")
private String sex;

/* 注意这个地方:并不是说加了这个注解,然后下面实现了addKnows这个方法在以后调用addKnows
* 就可以实现关系的增加,这是不对的,我看了很多教程没有说明。这个addKnows方法,只有在节点未被
* 添加之前,调用该方法添加关系,然后再调用UserService中的create方法,这样关系才会同时被添加到图
* 数据库中。如果想实现两个已有节点之间增加关系,需要单独实现
*/

@Relationship(type = "know" ,direction = Relationship.OUTGOING)
private Set<UserNode> knows = new HashSet<>();

public Long getNodeId() {
return nodeId;
}

public void setNodeId(Long nodeId) {
this.nodeId = nodeId;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public Set<UserNode> getKnows() {
return knows;
}

public void setKnows(Set<UserNode> knows) {
this.knows = knows;
}

public Boolean addKnows(UserNode to){
return this.knows.add(to);
}

@Override
public String toString() {
return "UserNode{" +
"nodeId=" + nodeId +
", name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}

public UserNode() {}
}

关系类(Know.java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.example.neo4jdemo.entity.relationship;

import com.example.neo4jdemo.entity.node.UserNode;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.voodoodyne.jackson.jsog.JSOGGenerator;
import org.neo4j.ogm.annotation.*;

/**
* @program: neo4jdemo
* @description: 知道关系类
* @author: chen
* @create: 2020-07-27
**/

@JsonIdentityInfo(generator= JSOGGenerator.class)
@RelationshipEntity(type = "know")
public class Know {

@Id
@GeneratedValue
private Long id;

@StartNode
private UserNode from;

@EndNode
private UserNode to;

public Long getId() {
return id;
}

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

public UserNode getFrom() {
return from;
}

public void setFrom(UserNode from) {
this.from = from;
}

public UserNode getTo() {
return to;
}

public void setTo(UserNode to) {
this.to = to;
}

public Know() {
}

public Know(UserNode from, UserNode to) {
this.from = from;
this.to = to;
}

@Override
public String toString() {
return "Know{" +
"id=" + id +
", from=" + from +
", to=" + to +
'}';
}
}

KnowRepository.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.example.neo4jdemo.repository;

import com.example.neo4jdemo.entity.relationship.Know;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.repository.query.Param;

/**
* @program: neo4jdemo
* @description: 知道关系接口类
* @author: chen
* @create: 2020-07-27
**/

public interface KnowRepository extends Neo4jRepository<Know,Long> {
@Query("MATCH (fromNode) WHERE id(fromNode) = {fromId} MATCH (toNode) WHERE id(toNode) = {toId} MATCH (fromNode)-[r]->(toNode) DELETE r")
void deleteByNodeId(@Param(value = "fromId") long fromId,@Param(value = "toId") long toId);
}

UserRepository.java

基础的增删改查Spring Data Neo4j已经封装好在Neo4jRepository里面了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.example.neo4jdemo.repository;

import com.example.neo4jdemo.entity.node.UserNode;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
importorg.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends Neo4jRepository<UserNode,Long> {

// @Query("MATCH (n:User) RETURN n ")
// List<UserNode> getUserNodeList();

// @Query("create (n:User{name:{name},age:{age},sex:{sex}}) RETURN n ")
// UserNode addUserNode(@Param("name") String name, @Param("age")int age, @Param("sex") String sex);
@Query("MATCH (n) WHERE id(n) = :#{#userNode.nodeId} SET n.name = :#{#userNode.name},n.age = :#{#userNode.age},n.sex = :#{#userNode.sex} RETURN n")
UserNode updateByNode(@Param("userNode") UserNode userNode);

}

UserService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

package com.example.neo4jdemo.service;

import com.example.neo4jdemo.entity.node.UserNode;
import com.example.neo4jdemo.entity.relationship.Know;
import java.util.List;
import java.util.Optional;

public interface UserService {

/**
* @Description: 添加user节点
* @Params: [UserNode]
* @return: int
* @Author: chen
* @Date: 2020/7/27
*/
UserNode create(UserNode userNode);

/**
* @Description: 删除
* @Author: chen
* @Date: 2020/7/27
*/
void deleteById(Long id);

/**
* @Description: 查询
* @Author: chen
* @Date: 2020/7/27
* @return
*/
Optional<UserNode> findById(long id);

/**
* @Description: 获取所有User节点
* @Params: null
* @return: List
* @Author: chen
* @Date: 2020/7/27
*/
List<UserNode> findAll();

/**
* @Description: 增加“知道”关系
* @Author: chen
* @Date: 2020/7/27
*/
Know addIKnows(UserNode fromNode, UserNode toNode);

UserNode updateByNode(UserNode userNode);

void deleteKnowByNodeId(long fromId,long toId);

}

UserServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

package com.example.neo4jdemo.service.impl;

import com.example.neo4jdemo.entity.node.UserNode;
import com.example.neo4jdemo.entity.relationship.Know;
import com.example.neo4jdemo.repository.KnowRepository;
import com.example.neo4jdemo.repository.UserRepository;
import com.example.neo4jdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;

@Service
public class UserServiceImpl implements UserService {

@Autowire
private UserRepository userRepository;

@Autowire
private KnowRepository knowRepository;

@Override
public UserNode create(UserNode userNode) {
return userRepository.save(userNode);
}

@Override
public void deleteById(Long id) {
userRepository.deleteById(id);
}

@Override
public Optional<UserNode> findById(long id) {
return userRepository.findById(id);
}

@Override
public List<UserNode> findAll() {
return (List<UserNode>) userRepository.findAll();
}

@Override
public Know addIKnows(UserNode fromNode, UserNode toNode) {
Know newKnow = new Know(fromNode,toNode);
return knowRepository.save(newKnow);
}

@Override
public UserNode updateByNode(UserNode userNode) {
return userRepository.updateByNode(userNode);
}

@Override
public void deleteKnowByNodeId(long fromId, long toId) {
knowRepository.deleteByNodeId(fromId,toId);
}
}

UserController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

package com.example.neo4jdemo.controller;

import com.example.neo4jdemo.entity.node.UserNode;
import com.example.neo4jdemo.entity.relationship.Know;
import com.example.neo4jdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;

/**
* @program: neo4jdemo
* @description: 控制层
* @author: chen
* @create: 2020-07-27
**/

@RestControlle
public class UserController {

@Autowired
private UserService userService;

/**
* @Description: 添加节点
* @Author: chen
* @Date: 2020/7/27
*/
@RequestMapping(path = "/add", method = RequestMethod.POST)
public UserNode addUserNode(@RequestBody UserNode userNode) {
return userService.create(userNode);
}

/**
* @Description: 根据id删除
* @Author: chen
* @Date: 2020/7/27
*/
@RequestMapping(path = "/delete", method = RequestMethod.POST)
public int delUserNodeById(@RequestParam(value = "id") long id) {
userService.deleteById(id);
System.out.println(id);
return 1;
}

/**
* @Description: 根据id更新
* @Author: chen
* @Date: 2020/7/27
*/
@RequestMapping(path = "/update", method = RequestMethod.POST)
public UserNode updateUserNodeByNode(@RequestBody UserNode userNode)
return userService.updateByNode(userNode)
}

@RequestMapping(path = "/get", method = RequestMethod.GET)
public UserNode getUserNodeById(@RequestParam(value = "id") long id) {

Optional<UserNode> optionalUserNode = userService.findById(id);

if(optionalUserNode.isPresent()){
return optionalUserNode.get();
}else{
return null;
}
}

/**
* @Description: 查找所有节点
* @Author: chen
* @Date: 2020/7/27
*/
@RequestMapping(path = "/list", method = RequestMethod.GET)
public List<UserNode> getUserNodeList() {
return userService.findAll();
}

@RequestMapping(path = "/addKnows", method = RequestMethod.POST)
public Know addKnowsById(@RequestParam(value = "from") long fromId, @RequestParam(value = "to") long toId) {

Optional<UserNode> fromOpt = userService.findById(fromId);
Optional<UserNode> toOpt = userService.findById(toId);

if(fromOpt.isPresent()&&toOpt.isPresent()){
return userService.addIKnows(fromOpt.get(),toOpt.get());
}else{
return null;
}
}

@RequestMapping(path = "/delKnows", method = RequestMethod.POST)
public String deleteKnowsByNodeId(@RequestParam(value = "from") long fromId, @RequestParam(value = "to") long toId) {

Optional<UserNode> fromOpt = userService.findById(fromId);
Optional<UserNode> toOpt = userService.findById(toId);

if(fromOpt.isPresent()&&toOpt.isPresent()){
userService.deleteKnowByNodeId(fromId,toId);
return "ok";
}else{
return "false";
}
}
}

Neo4jConfig.java 我也不知道干啥的

1
2
3
4
5
6
7
8
9
10
11
package com.example.neo4jdemo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableNeo4jRepositories(basePackages = "com.example.neo4jdemo.repository")
@EnableTransactionManagement // 激活SDN隐式事务
public class Neo4jConfig {
}

重点就是User中的那段注释,是我困扰了很久的问题,希望大家能够避坑。有什么问题可以留言。

Neo4j+SpringBoot实现节点以及关系的增删改查(Spring Data Neo4j)

http://leofitz1024.github.io/2020/07/28/Spring Boot/04/

作者

xchen

发布于

2020-07-28

更新于

2021-11-22

评论