SpringBoot 整合 Neo4J
2025-12-10
Docker安装
text
1docker run -d \
2 --name neo4j \
3 -p 7474:7474 \
4 -p 7687:7687 \
5 -e NEO4J_AUTH=neo4j/hello-agents-password \
6 neo4j:5SpringBoot
xml
1 <dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter-data-neo4j</artifactId>
4 </dependency>text
1
2@Configuration
3public class Neo4jConfig {
4
5 @Bean
6 public PlatformTransactionManager transactionManager(Driver driver) {
7 return new Neo4jTransactionManager(driver);
8 }
9}
10@Data
11@Node("Actor")
12public class ActorEntity {
13
14 @Id
15 @GeneratedValue
16 private Long id;
17
18 private final String name;
19
20 @Relationship(type = "演过")
21 private List<MovieEntity> movies = new ArrayList<>();
22
23 public ActorEntity(String name) {
24 this.name = name;
25 }
26}
27@Repository
28public interface ActorRepository extends Neo4jRepository<ActorEntity, Long> {
29
30 ActorEntity findOneByName(String name);
31
32 @Query("MATCH (n) DETACH DELETE n")
33 void deleteAllData();
34
35 @Query("""
36 MATCH (a:Actor {name: $actorName})
37 MATCH (m:Movie {title: $movieTitle})
38 MERGE (a)-[:写过]->(m)
39 """)
40 void createActedInRelation(String actorName, String movieTitle);
41}
42@Data
43@Node("Movie")
44public class MovieEntity {
45
46 @Id
47 @GeneratedValue
48 private Long id;
49
50 private final String title;
51
52 @Property("tagline")
53 private final String description;
54
55 @Relationship(type = "包含", direction = Relationship.Direction.OUTGOING)
56 private List<ActorEntity> actors = new ArrayList<>();
57
58 public MovieEntity(String title, String description) {
59 this.id = null;
60 this.title = title;
61 this.description = description;
62 }
63
64 public MovieEntity withId(Long id) {
65 if (this.id.equals(id)) {
66 return this;
67 } else {
68 MovieEntity newObject = new MovieEntity(this.title, this.description);
69 newObject.id = id;
70 return newObject;
71 }
72 }
73}
74@Repository
75public interface MovieRepository extends Neo4jRepository<MovieEntity, Long> {
76
77 MovieEntity findOneByTitle(String title);
78
79
80 @Query("""
81 MATCH (m:Movie {title: $title})
82 OPTIONAL MATCH (m)<-[:ACTED_IN]-(a:Actor)
83 RETURN m, collect(a) as actors
84 """)
85 MovieEntity loadMovieWithActors(String title);
86
87}
88package cn.lx.springai.neo4j;
89
90import cn.lx.springai.SpringAiApplication;
91import org.neo4j.cypherdsl.core.renderer.Configuration;
92import org.neo4j.cypherdsl.core.renderer.Dialect;
93import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore;
94import org.springframework.boot.SpringApplication;
95import org.springframework.context.ConfigurableApplicationContext;
96import org.springframework.context.annotation.Bean;
97import org.springframework.data.neo4j.core.schema.GeneratedValue;
98import org.springframework.data.neo4j.core.schema.Id;
99import org.springframework.data.neo4j.core.schema.Node;
100import org.springframework.data.neo4j.core.schema.Property;
101import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
102import org.springframework.jdbc.core.JdbcTemplate;
103import org.springframework.transaction.PlatformTransactionManager;
104import org.springframework.transaction.support.TransactionTemplate;
105
106import java.util.List;
107
108/**
109 * spring-ai
110 * 描述:
111 *
112 * @author liuxin
113 * 日期: 2025-12-09 15:51
114 **/
115public class Neo4jTest {
116
117
118 static Configuration cypherDslConfiguration() {
119 return Configuration.newConfig()
120 .withDialect(Dialect.NEO4J_4).build();
121 }
122
123 /**
124 * 先创建实体
125 * 然后创建关系
126 */
127 public static void test2(ActorRepository actorRepository, MovieRepository movieRepository, ConfigurableApplicationContext run) {
128 actorRepository.deleteAllData();
129 ActorEntity actor4 = new ActorEntity("吴承恩");
130 ActorEntity actor5 = new ActorEntity("曹雪芹");
131 MovieEntity movie5 = new MovieEntity("三国演义", "三分天下");
132 MovieEntity movie6 = new MovieEntity("红楼梦", "一群女人");
133 actorRepository.saveAll(List.of(actor5, actor4));
134 movieRepository.saveAll(List.of(movie5, movie6));
135 actorRepository.createActedInRelation("吴承恩", "三国演义");
136 }
137
138 /**
139 * 直接创建实体和关系
140 */
141 public static void insert(ActorRepository actorRepository, MovieRepository movieRepository, ConfigurableApplicationContext run) {
142 actorRepository.deleteAllData();
143 // 创建电影
144 MovieEntity movie1 = new MovieEntity("大话西游", "至尊宝与紫霞的爱情故事");
145 MovieEntity movie2 = new MovieEntity("功夫", "周星驰的经典功夫喜剧");
146 MovieEntity movie3 = new MovieEntity("喜剧之王", "尴尬而搞笑的演艺人生");
147 // 创建演员
148 ActorEntity actor1 = new ActorEntity("周星驰");
149 ActorEntity actor2 = new ActorEntity("吴孟达");
150 ActorEntity actor3 = new ActorEntity("朱茵");
151
152 actor1.getMovies().addAll(List.of(movie1, movie2, movie3));
153 actor2.getMovies().addAll(List.of(movie1, movie2));
154 actor3.getMovies().add(movie1);
155 // 保存演员(关系会自动保存)
156 actorRepository.saveAll(List.of(actor1, actor2, actor3));
157 }
158
159 public static void main(String[] args) {
160 ConfigurableApplicationContext run = SpringApplication.run(SpringAiApplication.class, args);
161 run.getBeanFactory().registerResolvableDependency(Configuration.class, cypherDslConfiguration());
162 Neo4jTransactionManager neo4jTransactionManager1 = run.getBean(Neo4jTransactionManager.class);
163 System.out.println(neo4jTransactionManager1);
164 MovieRepository movieRepository = run.getBean(MovieRepository.class);
165 ActorRepository actorRepository = run.getBean(ActorRepository.class);
166 test2(actorRepository, movieRepository, run);
167 }
168}
169控制台
http://localhost:7474/browser/
查询语句: MATCH(a:Actor)-[b:演过]-(c:Movie) RETURN a,b,c
查询所有: MATCH(n) return n