项目概况

SpringBoot 整合 Neo4J

2026-01-293 min read未分类
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:5

SpringBoot

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