neo4j入门

docker安装

1
mkdir -p ~/neo4j/{data,logs,plugins,conf}

~/neo4j目录下创建docker-compose.yml

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
version: '3.8'
services:
neo4j:
# 指定Neo4j镜像,:latest为最新版,也可指定具体版本如4.4.19、5.18.0
image: neo4j:latest
# 容器名,自定义
container_name: neo4j
# 开机自启
#restart: always
# 端口映射:宿主端口:容器端口(核心端口,不要随意改)
ports:
- "7474:7474" # Neo4j 浏览器Web界面端口
- "7687:7687" # Neo4j Bolt协议端口(程序连接用,如Java/Python客户端)
- "7473:7473" # HTTPS协议的Web界面端口(可选,一般不用)
# 环境变量配置(核心:设置初始密码、允许远程连接)
environment:
- NEO4J_AUTH=neo4j/123456 # 初始账号/密码:neo4j是固定用户名,密码自定义(如123456)
- NEO4J_server_memory_heap_initial__size=512m # 堆内存初始值,根据服务器配置调整
- NEO4J_server_memory_heap_max__size=2G # 堆内存最大值
- NEO4J_server_memory_pagecache_size=1G # 页缓存大小
# 数据卷挂载:本地目录映射到容器内,实现持久化
volumes:
- ~/neo4j/data:/data
- ~/neo4j/logs:/logs
- ~/neo4j/plugins:/plugins
- ~/neo4j/conf:/conf
# 资源限制(可选,根据服务器配置调整)
deploy:
resources:
limits:
cpus: '1'
memory: 4G
1
docker compose up -d

访问

http://127.0.0.1:7474

输入刚刚配置的用户名密码。

以例子来学习命令

例子概述

以学生、课程、老师为节点;选课、授课、任教为关系。

1. 节点类型(Label)& 属性

  • Student(学生):id (学号)、name (姓名)、age (年龄)、gender (性别)
  • Course(课程):id (课程号)、name (课程名)、credit (学分)、type (课程类型:必修 / 选修)
  • Teacher(老师):id (工号)、name (姓名)、subject (授课科目)、age (年龄)

2. 关系类型(Relationship)& 属性

  • STUDY(选课):Student → Course,属性:score (成绩)、semester (学期)
  • TEACH(授课):Teacher → Course,属性:teach_year (授课年份)
  • WORK_AT(任教):Teacher → (可选,无属性,指向学校,简化为固定值)

命令

一、基础操作:创建节点(CREATE / MERGE)

创建节点是图数据库的基础,推荐MERGE(不存在则创建,存在则匹配,避免重复),新手也可先学CREATE(直接创建,会重复)。

1. 单节点创建(CREATE)

1
2
3
4
5
6
7
8
9
10
11
// 创建1个学生节点
CREATE (s:Student {id: 202401, name: "张三", age: 20, gender: "男"})
RETURN s; // RETURN 用于返回创建的节点,可省略

// 创建1个课程节点
CREATE (c:Course {id: "C001", name: "Python基础", credit: 3, type: "必修"})
RETURN c;

// 创建1个老师节点
CREATE (t:Teacher {id: "T001", name: "李老师", subject: "计算机", age: 35})
RETURN t;

2.批量创建节点(CREATE 多个)

1
2
3
4
5
6
7
8
9
// 批量创建2个学生、2个课程、2个老师
CREATE
(s2:Student {id: 202402, name: "李四", age: 19, gender: "女"}),
(s3:Student {id: 202403, name: "王五", age: 20, gender: "男"}),
(c2:Course {id: "C002", name: "图数据库", credit: 2, type: "选修"}),
(c3:Course {id: "C003", name: "Java开发", credit: 3, type: "必修"}),
(t2:Teacher {id: "T002", name: "王老师", subject: "数学", age: 40}),
(t3:Teacher {id: "T003", name: "张老师", subject: "计算机", age: 32})
RETURN s2, s3, c2, c3, t2, t3;

3.防重复创建(MERGE 推荐)

1
2
3
4
// 若学号202401的学生不存在则创建,存在则直接匹配
MERGE (s:Student {id: 202401})
ON CREATE SET s.name = "张三", s.age = 20, s.gender = "男"
RETURN s;

ON CREATE SET:仅在节点创建时设置属性,避免覆盖已有数据。

二、核心操作:创建节点间的关系(CREATE / MERGE)

关系是图数据库的灵魂,格式为 (节点1)-[关系名:关系类型 {属性}]->(节点2),箭头表示关系方向。

1. 先匹配节点,再创建关系(推荐,避免创建无效关系)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 1. 张三(202401)选了Python基础(C001),成绩90,2024秋学期
MATCH (s:Student {id: 202401}), (c:Course {id: "C001"})
CREATE (s)-[r:STUDY {score: 90, semester: "2024秋"}]->(c)
RETURN s, r, c;

// 2. 李老师(T001)讲授Python基础(C001),2024年授课
MATCH (t:Teacher {id: "T001"}), (c:Course {id: "C001"})
CREATE (t)-[r:TEACH {teach_year: 2024}]->(c)
RETURN t, r, c;

// 3. 批量创建关系(李四/王五选课,张老师授课)
MATCH
(s2:Student {id: 202402}), (s3:Student {id: 202403}),
(c1:Course {id: "C001"}), (c2:Course {id: "C002"}),
(t3:Teacher {id: "T003"})
CREATE
(s2)-[:STUDY {score: 85, semester: "2024秋"}]->(c1),
(s2)-[:STUDY {score: 92, semester: "2024秋"}]->(c2),
(s3)-[:STUDY {score: 78, semester: "2024秋"}]->(c1),
(t3)-[:TEACH {teach_year: 2024}]->(c2),
(t3)-[:TEACH {teach_year: 2024}]->(c3),
(t1:Teacher {id: "T001"})-[:WORK_AT]->({name: "XX大学"}) // 直接创建带关系的匿名节点(学校)
RETURN *; // RETURN * 返回所有匹配/创建的节点和关系

2.防重复关系(MERGE 关系)

1
2
3
4
5
// 避免张三重复创建选C001的关系
MATCH (s:Student {id: 202401}), (c:Course {id: "C001"})
MERGE (s)-[r:STUDY {semester: "2024秋"}]->(c)
ON CREATE SET r.score = 90 // 仅创建时设成绩
RETURN s, r, c;

三、查询操作:MATCH (最常用,覆盖单节点 / 关系 / 多条件 / 聚合)

查询是 Cypher 的核心,MATCH 用于匹配节点 / 关系,搭配WHERE筛选、RETURN返回、ORDER BY排序、LIMIT限制结果,新手重点掌握。

1. 简单查询:匹配所有 / 指定类型节点

1
2
3
4
5
6
7
8
9
10
// 1. 查询所有节点(新手调试用,生产环境避免)
MATCH (n) RETURN n LIMIT 10; // LIMIT 限制返回10个,防止数据过多

// 2. 查询所有学生节点,返回姓名和年龄(指定属性,更简洁)
MATCH (s:Student) RETURN s.name, s.age;

// 3. 查询所有必修课程,按学分降序
MATCH (c:Course {type: "必修"})
RETURN c.name, c.credit
ORDER BY c.credit DESC;

2.带关系的查询:匹配节点 + 关系(核心)

1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. 查询张三选了哪些课程,返回课程名和成绩
MATCH (s:Student {name: "张三"})-[r:STUDY]->(c:Course)
RETURN s.name, c.name, r.score;

// 2. 查询谁教了Python基础(反向查询,箭头可省略)
MATCH (t:Teacher)-[r:TEACH]->(c:Course {name: "Python基础"})
RETURN t.name, r.teach_year;

// 3. 查询选了Python基础的所有学生姓名和成绩,按成绩升序
MATCH (s:Student)-[r:STUDY]->(c:Course {name: "Python基础"})
RETURN s.name, r.score
ORDER BY r.score ASC
LIMIT 5;

3.多条件筛选:WHERE 子句(复杂条件用,比直接写属性更灵活)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 1. 查询年龄≥20的男学生,选了学分≥3的课程
MATCH (s:Student)-[r:STUDY]->(c:Course)
WHERE s.age >= 20 AND s.gender = "男" AND c.credit >=3
RETURN s.name, c.name, r.score;

// 2. 查询成绩在80~90之间的选课记录
MATCH (s:Student)-[r:STUDY]->(c:Course)
WHERE r.score >= 80 AND r.score <= 90
RETURN s.name, c.name, r.score

// 3. 模糊查询:课程名包含「数据库」的课程
MATCH (c:Course)
WHERE c.name CONTAINS "数据库" // 还可用 STARTS WITH(以...开头)/ ENDS WITH(以...结尾)
RETURN c.name, c.type;

4.聚合查询:COUNT/SUM/AVG/MIN/MAX(统计分析用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 1. 统计学生总数、课程总数
MATCH (s:Student) RETURN COUNT(s) AS student_count;
MATCH (c:Course) RETURN COUNT(c) AS course_count;

// 2. 计算Python基础的平均成绩、最高/最低成绩
MATCH (s)-[r:STUDY]->(c:Course {name: "Python基础"})
RETURN
AVG(r.score) AS avg_score,
MAX(r.score) AS max_score,
MIN(r.score) AS min_score,
COUNT(s) AS study_count; // 选课人数

// 3. 统计每个学生的选课门数和总成绩,按选课门数降序
MATCH (s:Student)-[r:STUDY]->(c:Course)
WITH s, COUNT(c) AS course_num, SUM(r.score) AS total_score // WITH 临时传递结果
RETURN s.name, course_num, total_score
ORDER BY course_num DESC;

5.多跳关系查询:路径查询(查间接关联,如「学生→课程→老师」)

1
2
3
4
5
6
7
8
9
10
11
12
// 1. 查询张三的所有授课老师(学生→课程→老师,2跳关系)
MATCH (s:Student {name: "张三"})-[r1:STUDY]->(c:Course)<-[r2:TEACH]-(t:Teacher)
RETURN s.name, c.name, t.name;

// 2. 通用路径查询:匹配张三和所有老师的最短路径(*表示任意跳数,1..3表示1-3跳)
MATCH p=shortestPath((s:Student {name: "张三"})-[*]-(t:Teacher))
RETURN p;

// 3. 查询教过选修课程的老师,且老师年龄<40
MATCH (t:Teacher)-[r:TEACH]->(c:Course {type: "选修"})
WHERE t.age < 40
RETURN DISTINCT t.name; // DISTINCT 去重,避免老师教多门选修课重复显示

四、修改操作:SET (修改节点 / 关系的属性,新增 / 更新)

SET新增属性(节点 / 关系无该属性时)或更新属性(已有该属性时),搭配MATCH定位要修改的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 1. 修改节点属性:张三年龄加1,新增「专业」属性
MATCH (s:Student {name: "张三"})
SET s.age = s.age + 1, s.major = "计算机科学与技术"
RETURN s;

// 2. 修改关系属性:张三的Python基础成绩改为95
MATCH (s:Student {name: "张三"})-[r:STUDY]->(c:Course {name: "Python基础"})
SET r.score = 95
RETURN s.name, c.name, r.score;

// 3. 批量修改:所有必修课程学分加1
MATCH (c:Course {type: "必修"})
SET c.credit = c.credit + 1
RETURN c.name, c.credit;

五、删除操作:DELETE / REMOVE (别搞混!)

关键区别:

  • DELETE:删除节点关系(删除节点前必须先删除其所有关系,否则报错)
  • REMOVE:删除节点 / 关系的属性(不是删除对象本身)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// ******************** REMOVE:删除属性 ********************
// 删除张三的「专业」属性
MATCH (s:Student {name: "张三"})
REMOVE s.major
RETURN s;

// ******************** DELETE:删除关系 ********************
// 删除王五选Python基础的关系
MATCH (s:Student {name: "王五"})-[r:STUDY]->(c:Course {name: "Python基础"})
DELETE r
RETURN s, c;

// ******************** DELETE:删除节点(先删关系再删节点) ********************
// 删除课程C003(Java开发):先删其所有关系,再删节点
MATCH (c:Course {id: "C003"})-[r]-() // [r]-() 匹配该课程的所有入/出关系
DELETE r, c // 先删关系r,再删节点c
RETURN "删除成功";

// ******************** 清空所有数据(谨慎!生产环境禁用) ********************
MATCH (n) DETACH DELETE n; // DETACH DELETE 自动删除节点的所有关系,再删除节点

六、索引与约束(优化查询,保证数据唯一性)

当数据量变大时,索引能大幅提升查询速度;约束能保证节点属性的唯一性(如学号、课程号不能重复),新手提前了解,后续实战必用。

1. 创建索引(针对常用查询的属性,如学生 id、课程名)

1
2
3
4
5
// 为Student的id属性创建索引
CREATE INDEX idx_student_id FOR (s:Student) ON (s.id);

// 为Course的name属性创建索引
CREATE INDEX idx_course_name FOR (c:Course) ON (c.name);

2.创建唯一约束(保证属性值唯一,比索引更严格,重复创建会报错)

1
2
3
4
5
// 保证学生学号唯一(核心,避免重复创建同学号学生)
CREATE CONSTRAINT constraint_student_id IF NOT EXISTS FOR (s:Student) REQUIRE s.id IS UNIQUE;

// 保证课程号唯一
CREATE CONSTRAINT constraint_course_id IF NOT EXISTS FOR (c:Course) REQUIRE c.id IS UNIQUE;

3. 查看 / 删除索引 / 约束

1
2
3
4
5
6
7
8
// 查看所有索引和约束
SHOW INDEXES;

// 删除索引(根据索引名,从SHOW INDEXES结果中查)
DROP INDEX idx_course_name;

// 删除约束(根据约束名)
DROP CONSTRAINT constraint_student_id;

使用Neo4j Java Driver操作neo4j

pom.xml

1
2
3
4
5
6
<!-- Neo4j Java Driver 5.x 核心依赖 -->
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>5.18.0</version> <!-- 适配Neo4j 5.x,可随官方更新 -->
</dependency>
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
import org.neo4j.driver.*;
import static org.neo4j.driver.Values.parameters;

public class Neo4jJavaDriverDemo {
// 核心:驱动对象(全局单例,项目启动时创建,关闭时销毁)
private static final Driver DRIVER;

// 静态代码块初始化驱动(连接Neo4j,Bolt协议)
static {
// 连接信息:你的Neo4j地址(本地localhost,服务器填公网IP)、端口7687、账号neo4j、密码你配置的(如123456)
String uri = "bolt://localhost:7687";
String username = "neo4j";
String password = "123456";
// 初始化驱动,可配置连接池(默认连接池足够新手使用)
DRIVER = GraphDatabase.driver(uri, AuthTokens.basic(username, password));
}

// 1. 新增节点:创建学生节点(MERGE防重复)
public static void createStudent(Long id, String name, Integer age) {
// 写Cypher语句,用$占位符传参(避免注入,推荐)
String cypher = "MERGE (s:Student {id: $id, name: $name, age: $age}) RETURN s";
// try-with-resources 自动关闭会话(Session),无需手动close
try (Session session = DRIVER.session()) {
// 执行Cypher,parameters传参,run()同步执行
Result result = session.run(cypher, parameters("id", id, "name", name, "age", age));
// 遍历结果
result.list().forEach(record -> System.out.println("创建学生:" + record.get("s").asMap()));
}
}

// 2. 查询操作:查询80~90分的选课记录(你之前的核心需求)
public static void queryStudyScore() {
String cypher = "MATCH (s:Student)-[r:STUDY]->(c:Course) WHERE r.score >= $min AND r.score <= $max RETURN s.name, c.name, r.score";
try (Session session = DRIVER.session()) {
Result result = session.run(cypher, parameters("min", 80, "max", 90));
// 遍历结果,封装为自定义对象(新手先打印,后续可封装)
result.list().forEach(record -> {
String studentName = record.get("s.name").asString();
String courseName = record.get("c.name").asString();
Integer score = record.get("r.score").asInt();
System.out.printf("学生:%s,课程:%s,成绩:%d%n", studentName, courseName, score);
});
}
}

// 3. 事务操作:批量创建节点(成功则提交,失败则回滚)
public static void batchCreateWithTransaction() {
try (Session session = DRIVER.session()) {
// 开启事务,executeWrite表示写操作(读操作用executeRead)
session.executeWrite(tx -> {
// 批量执行Cypher
tx.run("MERGE (s1:Student {id: 202405, name: '赵六', age: 21})");
tx.run("MERGE (s2:Student {id: 202406, name: '孙七', age: 20})");
tx.run("MERGE (c4:Course {id: 'C005', name: 'MySQL', credit: 3, type: '必修'})");
return null; // 提交事务
});
System.out.println("批量创建成功,事务已提交");
} catch (Exception e) {
System.out.println("批量创建失败,事务已回滚:" + e.getMessage());
}
}

// 关闭驱动(项目关闭时执行,如Spring的销毁方法)
public static void closeDriver() {
if (DRIVER != null) {
DRIVER.close();
}
}

// 主方法测试
public static void main(String[] args) {
try {
createStudent(202404L, "测试学生", 20); // 新增学生
queryStudyScore(); // 查询成绩
batchCreateWithTransaction(); // 批量创建(事务)
} finally {
closeDriver(); // 最后关闭驱动
}
}
}

Spring Data Neo4j操作neo4j

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
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
spring:
application:
name: neo4j_springdata
neo4j:
uri: bolt://localhost:7687 # Bolt协议地址,和Driver一致
authentication:
username: neo4j # 账号
password: 123456 # 你的密码
data:
neo4j:
repositories:
enabled: true # 开启Repository自动扫描(默认开启)

server:
port: 8081
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
package com.test.neo4j_springdata.domain;// 1. 学生节点实体:@Node映射Neo4j节点,label为Student

import lombok.Data;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;
import org.springframework.data.neo4j.core.schema.Relationship;

import java.util.List;

@Data
@Node(value = "Student") // 对应Neo4j的Student标签
public class Student {
@Id // 对应Neo4j的唯一属性id(和你创建的唯一约束一致)
private Long id;
@Property(name = "name") // 映射节点属性name(可省略,字段名一致即可)
private String name;
private Integer age;
private String gender;

// 无参构造器(SDN必须)、有参构造器、getter/setter、toString
public Student() {}
public Student(Long id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}

// 映射STUDY关系:方向OUTGOING(出边,Student→Course),类型STUDY,关联StudyRelation
@Relationship(type = "STUDY", direction = Relationship.Direction.OUTGOING)
private List<StudyRelation> studyRelations;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.test.neo4j_springdata.domain;

import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;

// 2. 课程节点实体:@Node映射Course标签
@Node(value = "Course")
public class Course {
@Id
private String id; // 课程号是字符串(C001)
private String name;
private Integer credit;
private String type;

public Course() {}
public Course(String id, String name, Integer credit) {
this.id = id;
this.name = name;
this.credit = credit;
}
// 省略getter/setter/toString
}
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
package com.test.neo4j_springdata.domain;

import lombok.Data;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.RelationshipProperties;
import org.springframework.data.neo4j.core.schema.TargetNode;

@Data
@RelationshipProperties // 标记这是关系属性实体
public class StudyRelation {

@Id
@GeneratedValue
private Long id;

private Integer score; // 选课成绩(关系属性)
private String semester; // 学期(关系属性)
@TargetNode // 关系的目标节点(Student → Course,目标是Course)
private Course course;

public StudyRelation() {}
public StudyRelation(Integer score, String semester, Course course) {
this.score = score;
this.semester = semester;
this.course = course;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.test.neo4j_springdata.repository;// 学生Repository:Neo4jRepository<实体类, 主键类型>

import com.test.neo4j_springdata.domain.Student;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository
public interface StudentRepository extends Neo4jRepository<Student, Long> {
// 1. 基础查询:根据姓名查询学生(Spring自动解析方法名,无需手写Cypher)
List<Student> findByName(String name);

// 2. 自定义Cypher:查询80~90分的选课记录(你的核心需求,@Query注解)
// 用:param传参,和Spring的参数绑定一致
@Query("MATCH (s:Student)-[r:STUDY]->(c:Course) WHERE r.score >= $min AND r.score <= $max RETURN s.name, c.name, r.score")
List<Object[]> queryStudyScoreBetween(Integer min, Integer max);
}
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
package com.test.neo4j_springdata.service;

import com.test.neo4j_springdata.domain.Student;
import com.test.neo4j_springdata.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Service
public class StudentService {
@Autowired
private StudentRepository studentRepository;

// 新增学生(@Transactional开启事务,Spring自动管理)
@Transactional
public Student createStudent(Student student) {
return studentRepository.save(student); // save():新增/更新(根据主键)
}

// 查询80~90分的选课记录
public List<Object[]> queryStudyScore() {
return studentRepository.queryStudyScoreBetween(80, 90);
}

// 根据姓名查询学生
public List<Student> findStudentByName(String name) {
return studentRepository.findByName(name);
}
}
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
package com.test.neo4j_springdata.controller;

import com.test.neo4j_springdata.domain.Student;
import com.test.neo4j_springdata.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @author : hanqc
* @date : 2026/2/4 11:15
* @description
*/
@RestController
@RequestMapping("/student")
public class StudentController {

@Autowired
private StudentService studentService;

@RequestMapping("/add")
public String add() {
studentService.createStudent(new Student(1L, "hanqc", 18));
return "添加成功";
}

@RequestMapping("/query")
public String query() {
return studentService.queryStudyScore().toString();
}

@RequestMapping("/queryByName")
public String queryByName() {
return studentService.findStudentByName("hanqc").toString();
}

}

neo4j入门
http://hanqichuan.com/2026/02/03/其他工具/neo4j入门/
作者
韩启川
发布于
2026年2月3日
许可协议