SpringBoot整合Neo4j,最新版本適用,超通俗詳細講解
0.前言
? 跟著班導師做項目的時候遇到社交網(wǎng)絡的部分,而傳統(tǒng)的關系數(shù)據(jù)庫不能很好解決數(shù)據(jù)之間的關系,因此采用圖數(shù)據(jù)的方式進行存儲。Neo4j算是主流的圖數(shù)據(jù)庫,多應用于知識圖譜、社交網(wǎng)絡等。
? 這兩天學習SpringBoot時碰到了很多問題
- springboot集合neo4j引用了org.neo4j的包,報錯Required identifier property not found for class
- 用SpringBoot集成neo4j,查詢報錯Could not find mappable nodes or relationships inside Record
- org.springframework.data.neo4j.core.schema中沒有@NodeEntity,@StartNode,@EndNode
- RelationShip無法注解在實體關系類中
- nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.neo4j.ogm.session.SessionFactory] sessionFactory找不到
看了(128條消息) 【最新】Neo4j官方建議Spring Boot 2.4.及以上版本用Neo4j Java Driver代替The Spring Boot starter_學到一寸是一寸的博客-CSDN博客的博客后才知道是因為SpringBoot版本較高(2.4以上)時集成的Neo4j的API規(guī)則方法在變化。但是他的博客還是沒有說明如何使用類似@Node的注解,自己特意去查了Neo4j官方文檔和Spring Neo4j的官方文檔并進行總結整理發(fā)出來。
本文將解決的問題
- SpringBoot高版本(2.4以上)+Neo4j的配置
- 使用@Node等注解操作簡化Neo4j
- 一些簡單的cypherQuery(很類似MySQL的SQL語句)用法解釋
- 利用Repository(類似MyBatisPlus操作的Mapper接口)對圖數(shù)據(jù)進行CRUD
- 不使用Repository而使用Neo4jTemplate直接對圖數(shù)據(jù)進行CRUD
TODO
- id的生成
- 分頁查詢
本文將會結合官網(wǎng)的一個 【導演-電影-演員】關系圖來進行實現(xiàn)。以新海誠導演的《你的名字》為例。
[
{
"n": {
"identity": 10,
"labels": [
"Movie"
],
"properties": {
"tagline": "影片講述了男女高中生在夢中相遇,并尋找彼此的故事。",
"title": "你的名字"
}
}
},
{
"n": {
"identity": 11,
"labels": [
"Person"
],
"properties": {
"born": 1997,
"name": "上白石萌音"
}
}
},
{
"n": {
"identity": 12,
"labels": [
"Person"
],
"properties": {
"born": 1993,
"name": "神木隆之介"
}
}
},
{
"n": {
"identity": 13,
"labels": [
"Person"
],
"properties": {
"born": 1973,
"name": "新海誠"
}
}
}
]
1.初始化Spring Boot項目添加依賴
注:本文所使用SpringBoot版本為2.7.4,Java8;(Java8+均可),neo4j的安裝不再贅述,請?zhí)崆鞍惭b配置好
1.初始化項目,添加依賴
指定對應的SpringBoot版本(注意本文適配2.4版本及以上)和相應的依賴,當然也可以后續(xù)pom依賴中添加坐標(注意pom有兩個neo4j相關的依賴)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>Neo4jDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Neo4jDemo</name>
<description>Neo4jDemo</description>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<!-- neo4j 驅(qū)動 這個需要自己手動添加一下 -->
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
</dependency>
<!-- neo4j 操作實體注解需要 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.配置Neo4j
spring:
neo4j:
uri: bolt://<YourNeo4jIpAddress>:7687
authentication:
username: <yourUserName>
password: <yourPassword>
# 指定數(shù)據(jù)庫
data:
neo4j:
database: <yourDatabase>
創(chuàng)建utils
包,并在該包下創(chuàng)建ExampleCommandLineRunner
來裝配Driver和Session
package com.example.neo4jdemo.utils;
import lombok.extern.slf4j.Slf4j;
import org.neo4j.driver.*;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ExampleCommandLineRunner implements CommandLineRunner {
private final Driver driver;
private final ConfigurableApplicationContext applicationContext;
public final Session session;
@Bean
Session session(){
return session;
}
// Autowire the Driver bean by constructor injection
public ExampleCommandLineRunner(Driver driver, ConfigurableApplicationContext applicationContext) {
this.driver = driver;
this.applicationContext = applicationContext;
this.session = driver.session();
}
@Override
public void run(String... args) throws Exception {
}
}
2.創(chuàng)建實體類節(jié)點
1.節(jié)點
節(jié)點介紹:
創(chuàng)建entity
包,添加實體類:PersonEntity
和MovieEntity
package com.example.neo4jdemo.entity;
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.Node;
@Node("Person")
@Data
public class PersonEntity {
@Id
@GeneratedValue
private Long id;
private String name;
private Integer born;
public PersonEntity(Integer born, String name) {
this.name = name;
this.born = born;
}
}
package com.example.neo4jdemo.entity;
import lombok.Data;
import org.springframework.data.neo4j.core.schema.*;
import java.util.ArrayList;
import java.util.List;
/**
* Movie實體類,一個neo4j的節(jié)點
*/
@Node(labels = "Movie") // 標簽名,labels可以缺省
@Data
public class MovieEntity {
@Id
@GeneratedValue // Id自增
private Long id;
private final String title;
@Property("tagline") // 映射到neo4j的屬性名
private final String description;
public MovieEntity(String title, String description) {
this.id = null;// 生成node時自動生成
this.title = title;
this.description = description;
}
// 用戶指定特定的Id
public MovieEntity withId(Long id) {
if (this.id!= null && this.id.equals(id)) {
return this;
} else {
MovieEntity newObject = new MovieEntity(this.title, this.description);
newObject.id = id;
return newObject;
}
}
}
1.withId在需要指定節(jié)點id而非自動生成時使用。
2.注意到除了id外的屬性均被final修飾,一種構造優(yōu)化,提高執(zhí)行效率:(來自Spring Data Neo4j)
This gives us a roundabout 25% performance boost over reflection. For the domain class to be eligible for such optimization, it needs to adhere to a set of constraints:
- Types must not reside in the default or under the
java
package.- Types and their constructors must be
public
- Types that are inner classes must be
static
.- The used Java Runtime must allow for declaring classes in the originating
ClassLoader
. Java 9 and newer impose certain limitations.By default, Spring Data attempts to use generated property accessors and falls back to reflection-based ones if a limitation is detected.
2.節(jié)點間的關系
關系解釋:(以ACTED_IN即參演關系為例)
創(chuàng)建Roles
和完善MovieEntity
package com.example.neo4jdemo.entity;
import org.springframework.data.neo4j.core.schema.RelationshipId;
import org.springframework.data.neo4j.core.schema.RelationshipProperties;
import org.springframework.data.neo4j.core.schema.TargetNode;
import java.util.List;
/**
* 定義一個關系屬性
*/
@RelationshipProperties
public class Roles {
@RelationshipId
private Long id;
private final List<String> roles;
@TargetNode // 相當于@StartNode
private final PersonEntity person;
// 參數(shù)1是目標關系實體節(jié)點 參數(shù)2是關系屬性
// Roles 參數(shù)1:Person實體,演員的出生年和姓名;參數(shù)2:演員名字列表(考慮到一個演員可能參演多個角色)
public Roles(PersonEntity person, List<String> roles) {
this.person = person;
this.roles = roles;
}
public List<String> getRoles() {
return roles;
}
}
注意這些關系**@TargetNode
修飾的是關系箭頭的尾部, 最終的箭頭指向是當前實體**,即TargetNode(PersonEntity)->當前定義Relationship的實體(MovieEntity)
package com.example.neo4jdemo.entity;
import lombok.Data;
import org.springframework.data.neo4j.core.schema.*;
import java.util.ArrayList;
import java.util.List;
/**
* Movie實體類,一個neo4j的節(jié)點
*/
@Node(labels = "Movie") // 標簽名,labels可以缺省
@Data
public class MovieEntity {
...(上面 1.節(jié)點 有)
// 定義一個關系(參演)[direction]
@Relationship(type = "ACTED_IN", direction = Relationship.Direction.INCOMING)
private List<Roles> actorsAndRoles = new ArrayList<>();
// 定義一個關系(導演)
@Relationship(type = "DIRECTED", direction = Relationship.Direction.INCOMING)
private List<PersonEntity> directors = new ArrayList<>();
// 注意這些關系最終的箭頭指向是當前實體,即TargetNode(PersonEntity)->當前定義Relationship的實體(MovieEntity)
}
3.CRUD
Cypher Query基本使用
了解即可,有封裝好的api使用,可以先跳過不看,看3.b部分。
- 創(chuàng)建
# 查詢name等于 $name 的 label為Person的實體類集合 MATCH (n:Person {name: $name}) RETURN n 或者 MATCH (n:Person) WHERE n.name = $name RETURN n
n是一個變量
$name 對應map的key
{ } 是 where 篩選的簡寫
Return 返回符合篩選條件的變量n
查找
# 查詢Person和Movie之間 關系種類為ACTED_IN且關系屬性role = $roles 的實體類集合 MATCH (person:Person) -[ relation:ACTED_IN ]-> (movie:Movie) WHERE relation.roles = $roles RETURN person 等價于 MATCH (person:Person) -[ relation:ACTED_IN ]-> (:Movie) WHERE relation.roles = $roles RETURN person
person、relation、movie是變量
:Person 、:Movie 用:后面接Label,
person:Person
有點類似變量聲明,如果不使用完全可以省略不寫用-[]-> 來表示關系的type以及指向
修改
# 新增屬性(Person本來只有name和born屬性,新增age屬性,一般不用) MATCH (n:Person) WHERE n.name = '新海誠' SET n.age = 50 # 修改屬性 MATCH (n:Person) WHERE n.name = "新津城" SET n.name = "新海誠" # 新增/修改多個屬性 MATCH (n:Person) WHERE n.name = '新海誠' SET n.age = 50, n.name="新津城"
- 刪除
# 刪除屬性(一般不用) MATCH (n:Person) WHERE n.name = "新津城" REMOVE n.age # 刪除關系(新海誠的導演關系刪除) MATCH (n:Person) -[k:DIRECTED]-> (m:Movie) WHERE n="新海誠" DELETE k # 刪除節(jié)點 MATCH (n:Person) WHERE n.name = "新海誠" DELETE n // 當該實體仍有關系時會報錯,必須先刪除關系再刪除節(jié)點 # 刪除節(jié)點(會刪除節(jié)點實體和他關聯(lián)的屬性) MATCH (n:Person) WHERE n.name = "新海誠" DETACH DELETE n
3.a 使用Neo4jTemplate對圖數(shù)據(jù)進行CRUD
1.創(chuàng)建節(jié)點和關系
// 創(chuàng)建節(jié)點實體
MovieEntity movie = new MovieEntity("你的名字","影片講述了男女高中生在夢中相遇,并尋找彼此的故事。");// 電影實體節(jié)點
// 定義(參演)關系
// new Roles 參數(shù)1:Person實體,演員的出生年和姓名;參數(shù)2:演員名字列表(考慮到一個演員可能參演多個角色)
// 參數(shù)1是目標關系實體節(jié)點 參數(shù)2是關系屬性
Roles roles1 = new Roles(new PersonEntity(1998,"上白石萌音"), Collections.singletonList("宮水三葉"));
Roles roles2 = new Roles(new PersonEntity(1993,"神木隆之介"), Collections.singletonList("立花瀧"));
PersonEntity director = new PersonEntity(1973,"新海誠");
// 添加movie的演員實體,加入(參演)關系
movie.getActorsAndRoles().add(roles1);
movie.getActorsAndRoles().add(roles2);
movie.getDirectors().add(director);
// 存入圖數(shù)據(jù)庫持久化
neo4jTemplate.save(movie);
結果:
2.查詢節(jié)點
// 查詢(不太推薦用Neo4jTemplate進行過濾查詢,因為需要手動寫cypherQuery,需要開發(fā)人員了解一下cypherQuery的寫法)
Optional<PersonEntity> person;
// 1. 通過id查詢
person = neo4jTemplate.findById(12, PersonEntity.class);
System.out.println("id為12號的Person節(jié)點:\n"+person);
// 2. 通過屬性查詢節(jié)點,如name 需要手寫cypherQuery語句
Map<String,Object> map = new HashMap<>();
map.put("name","新海誠");
// 兩種寫法都對,看個人喜好 n是一個變量隨意取,{}或者where填寫query的filter過濾條件
person = neo4jTemplate.findOne("MATCH (n:Person {name: $name}) RETURN n",map, PersonEntity.class);
// person = neo4jTemplate.findOne("MATCH (n:Person) WHERE n.name = $name RETURN n",map, PersonEntity.class);
System.out.println("\n查詢名字為新海誠的Person節(jié)點:\n"+person);
// 3. 通過屬性關系查詢節(jié)點
map = new HashMap<>();
map.put("roles",Collections.singletonList("宮水三葉"));
// 方法1.使用toExecutableQuery查詢
QueryFragmentsAndParameters parameters = new QueryFragmentsAndParameters(
"MATCH (person:Person) -[ relation:ACTED_IN]-> (movie:Movie) \n" +
"WHERE relation.roles = $roles\n" +
"RETURN person",map);
List<PersonEntity> roles = neo4jTemplate.toExecutableQuery(PersonEntity.class, parameters).getResults();
// 方法2.使用findOne查詢
// Optional<PersonEntity> roles = neo4jTemplate.findOne(
// "MATCH (person:Person) -[ relation:ACTED_IN]-> (movie:Movie) \n" +
// "WHERE relation.roles = $roles\n" +
// "RETURN person",map,PersonEntity.class);
System.out.println("\n查詢角色為“宮水三葉”的演員:\n"+roles);
結果:
3.更新節(jié)點信息
Long userId = person.get().getId();// 記錄當前查詢的"新海誠"的節(jié)點id
// 更新①---------更新“新海誠”的name為曾用名“新津誠”(這是他的曾用名)
map.put("name","新海誠");
map.put("usedName","新津誠");
QueryFragmentsAndParameters queryFragmentsAndParameters =
new QueryFragmentsAndParameters(
"MATCH (n:Person{name: $name}) SET n.name = $usedName",
map);
neo4jTemplate.toExecutableQuery(
PersonEntity.class,
queryFragmentsAndParameters).getResults();
Optional<PersonEntity> person1 = neo4jTemplate.findById(userId, PersonEntity.class);
System.out.println("\n更新“新海誠”的name為曾用名“新津誠”(這是他的曾用名):\n"+person1);
// 更新②---------更新“新津誠”的name為“新海誠”
person.get().setName("新海誠");
neo4jTemplate.save(person.get());
Optional<PersonEntity> person2 = neo4jTemplate.findById(userId, PersonEntity.class);
System.out.println("\n更新“新津誠”的name為“新海誠”:\n"+person2);
結果:
4.刪除節(jié)點
// 刪除所有節(jié)點和關系(刪除節(jié)點會響應刪除關聯(lián)關系)[也可以用cypherQuery執(zhí)行,不再贅述]
neo4jTemplate.deleteAll(MovieEntity.class);
neo4jTemplate.deleteAll(PersonEntity.class);
上方的api根據(jù)實際情況使用,不再贅述。
5.完整代碼
/**
* 沒有Repository情況下使用Neo4jTemplate操作數(shù)據(jù)
* @param neo4jTemplate
*/
@Test
void TestNoRepository(@Autowired Neo4jTemplate neo4jTemplate){
// 刪除所有節(jié)點和關系(刪除節(jié)點會響應刪除關聯(lián)關系),避免后續(xù)創(chuàng)建節(jié)點重復影響
neo4jTemplate.deleteAll(MovieEntity.class);
neo4jTemplate.deleteAll(PersonEntity.class);
// 創(chuàng)建節(jié)點實體
MovieEntity movie = new MovieEntity("你的名字","影片講述了男女高中生在夢中相遇,并尋找彼此的故事。");
// new Roles 參數(shù)1:Person實體,演員的出生年和姓名;參數(shù)2:演員名字列表(考慮到一個演員可能參演多個角色)
// 參數(shù)1是目標關系實體節(jié)點 參數(shù)2是關系屬性
Roles roles1 = new Roles(new PersonEntity(1998,"上白石萌音"), Collections.singletonList("宮水三葉"));
Roles roles2 = new Roles(new PersonEntity(1993,"神木隆之介"), Collections.singletonList("立花瀧"));
PersonEntity director = new PersonEntity(1973,"新海誠");
// 添加movie的演員實體,加入(參演)關系
movie.getActorsAndRoles().add(roles1);
movie.getActorsAndRoles().add(roles2);
movie.getDirectors().add(director);
// 存入圖數(shù)據(jù)庫持久化
neo4jTemplate.save(movie);
// 查詢(不太推薦用Neo4jTemplate進行過濾查詢,因為需要手動寫cypherQuery,需要開發(fā)人員了解一下cypherQuery的寫法)
Optional<PersonEntity> person;
// 1. 通過id查詢
person = neo4jTemplate.findById(12, PersonEntity.class);
System.out.println("id為12號的Person節(jié)點:\n"+person);
// 2. 通過屬性查詢節(jié)點,如name 需要手寫cypherQuery語句
Map<String,Object> map = new HashMap<>();
map.put("name","新海誠");
// 兩種寫法都對,看個人喜好 n是一個變量隨意取,{}或者where填寫query的filter過濾條件
person = neo4jTemplate.findOne("MATCH (n:Person {name: $name}) RETURN n",map, PersonEntity.class);
// person = neo4jTemplate.findOne("MATCH (n:Person) WHERE n.name = $name RETURN n",map, PersonEntity.class);
System.out.println("\n查詢名字為新海誠的Person節(jié)點:\n"+person);
// 3. 通過屬性關系查詢節(jié)點
map = new HashMap<>();
map.put("roles",Collections.singletonList("宮水三葉"));
// 方法1.使用toExecutableQuery查詢
QueryFragmentsAndParameters parameters = new QueryFragmentsAndParameters(
"MATCH (person:Person) -[ relation:ACTED_IN]-> (movie:Movie) \n" +
"WHERE relation.roles = $roles\n" +
"RETURN person",map);
List<PersonEntity> roles = neo4jTemplate.toExecutableQuery(PersonEntity.class, parameters).getResults();
// 方法2.使用findOne查詢
// Optional<PersonEntity> roles = neo4jTemplate.findOne(
// "MATCH (person:Person) -[ relation:ACTED_IN]-> (movie:Movie) \n" +
// "WHERE relation.roles = $roles\n" +
// "RETURN person",map,PersonEntity.class);
System.out.println("\n查詢角色為“宮水三葉”的演員:\n"+roles);
Long userId = person.get().getId();// 記錄當前查詢的"新海誠"的節(jié)點id
// 更新①---------更新“新海誠”的name為曾用名“新津誠”(這是他的曾用名)
map.put("name","新海誠");
map.put("usedName","新津誠");
QueryFragmentsAndParameters queryFragmentsAndParameters =
new QueryFragmentsAndParameters(
"MATCH (n:Person{name: $name}) SET n.name = $usedName",
map);
neo4jTemplate.toExecutableQuery(
PersonEntity.class,
queryFragmentsAndParameters).getResults();
Optional<PersonEntity> person1 = neo4jTemplate.findById(userId, PersonEntity.class);
System.out.println("\n更新“新海誠”的name為曾用名“新津誠”(這是他的曾用名):\n"+person1);
// 更新②---------更新“新津誠”的name為“新海誠”
person.get().setName("新海誠");
neo4jTemplate.save(person.get());
Optional<PersonEntity> person2 = neo4jTemplate.findById(userId, PersonEntity.class);
System.out.println("\n更新“新津誠”的name為“新海誠”:\n"+person2);
}
3.b 使用repository對圖數(shù)據(jù)進行CRUD
1.創(chuàng)建Repository
新建repository
包,創(chuàng)建PersonRepository
和MovieRepository
package com.example.neo4jdemo.repository;
import com.example.neo4jdemo.entity.PersonEntity;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface PersonRepository extends Neo4jRepository<PersonEntity, Long> {
}
package com.example.neo4jdemo.repository;
import com.example.neo4jdemo.entity.MovieEntity;
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 MovieRepository extends Neo4jRepository<MovieEntity, Long> {
}
2.創(chuàng)建節(jié)點和關系
// 創(chuàng)建節(jié)點
MovieEntity movie = new MovieEntity("你的名字","影片講述了男女高中生在夢中相遇,并尋找彼此的故事。");
Roles roles1 = new Roles(new PersonEntity(1998,"上白石萌音"), Collections.singletonList("宮水三葉"));
Roles roles2 = new Roles(new PersonEntity(1993,"神木隆之介"), Collections.singletonList("立花瀧"));
PersonEntity director = new PersonEntity(1973,"新海誠");
// 添加關系
movie.getActorsAndRoles().add(roles1);
movie.getActorsAndRoles().add(roles2);
movie.getDirectors().add(director);
// 存入圖數(shù)據(jù)庫持久化
movieRepository.save(movie);
3.查詢
需求:根據(jù)Person的名字查詢對應節(jié)點
在PersonRepository
中添加方法:
@Repository
public interface PersonRepository extends Neo4jRepository<PersonEntity, Long> {
PersonEntity findPersonEntityByName(String name);
}
在MovieRepository
中添加方法:
@Repository
public interface MovieRepository extends Neo4jRepository<MovieEntity, Long> {
// @Query("MATCH (n:Movie) WHERE id(n) = $0 RETURN n") 這種方法是自己寫Query語句進行查詢
List<MovieEntity> findMovieEntitiesById(Long id);
MovieEntity findMovieEntityByTitle(String title);
}
查詢:
// 查詢
// 查詢
PersonEntity person = personRepository.findPersonEntityByName("上白石萌音");
System.out.println("查詢名字為“上白石萌音”的PersonEntity:"+person);
MovieEntity movieQueried = movieRepository.findMovieEntityByTitle("你的名字");
System.out.println("查詢名字為“你的名字”的MovieEntity:"+movieQueried);
結果:
查詢名字為“上白石萌音”的PersonEntity:
PersonEntity(id=15, name=上白石萌音, born=1998)
查詢名字為“你的名字”的MovieEntity:
MovieEntity(id=14, title=你的名字, description=影片講述了男女高中生在夢中相遇,并尋找彼此的故事。, actorsAndRoles=[com.example.neo4jdemo.entity.Roles@d902300, com.example.neo4jdemo.entity.Roles@2db33feb], directors=[PersonEntity(id=17, name=新海誠, born=1973)])
4.更新
// 更新(更新主要是三步:1.獲取實體id;2.修改實體屬性;3.更新實體)
// 注意:repository的save方法【對應的實體若id一致】則為修改,否則為新建。
Long personId = person.getId();
person.setBorn(1997);
personRepository.save(person);
person = personRepository.findPersonEntityByName("上白石萌音");
System.out.println(personId == person.getId()?"\n更新“上白石萌音”出生日期為1997信息成功?。篭n"+person:"更新信息失??!");
5.刪除
// 刪除所有節(jié)點和關系
movieRepository.deleteAll();
personRepository.deleteAll();
6.完整代碼
/**
* 使用repository操作圖數(shù)據(jù)
*/
@Test
void testByRepository(@Autowired MovieRepository movieRepository, @Autowired PersonRepository personRepository){
// 刪除所有節(jié)點和關系(刪除節(jié)點會響應刪除關聯(lián)關系),避免后續(xù)創(chuàng)建節(jié)點重復影響
movieRepository.deleteAll();
personRepository.deleteAll();
// 創(chuàng)建節(jié)點
MovieEntity movie = new MovieEntity("你的名字","影片講述了男女高中生在夢中相遇,并尋找彼此的故事。");
Roles roles1 = new Roles(new PersonEntity(1998,"上白石萌音"), Collections.singletonList("宮水三葉"));
Roles roles2 = new Roles(new PersonEntity(1993,"神木隆之介"), Collections.singletonList("立花瀧"));
PersonEntity director = new PersonEntity(1973,"新海誠");
// 添加關系
movie.getActorsAndRoles().add(roles1);
movie.getActorsAndRoles().add(roles2);
movie.getDirectors().add(director);
// 存入圖數(shù)據(jù)庫持久化
movieRepository.save(movie);
// 查詢
PersonEntity person = personRepository.findPersonEntityByName("上白石萌音");
System.out.println("\n查詢名字為“上白石萌音”的PersonEntity:\n"+person);
MovieEntity movieQueried = movieRepository.findMovieEntityByTitle("你的名字");
System.out.println("\n查詢名字為“你的名字”的MovieEntity:\n"+movieQueried);
// 更新(更新主要是三步:1.獲取實體id;2.修改實體屬性;3.更新實體)
// 注意:repository的save方法【對應的實體若id一致】則為修改,否則為新建。
Long personId = person.getId();
person.setBorn(1997);
personRepository.save(person);
person = personRepository.findPersonEntityByName("上白石萌音");
System.out.println(personId == person.getId()?"\n更新“上白石萌音”出生日期為1997信息成功?。篭n"+person:"更新信息失??!");
}
4.參考與源碼
案例來自官方文檔:
https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#conversions https://neo4j.com/docs/aura/auradb/connecting-applications/spring-boot/
源碼戳這里:文章來源:http://www.zghlxwxcb.cn/news/detail-788720.html
https://github.com/WuYiheng-Og/neo4j_springboot文章來源地址http://www.zghlxwxcb.cn/news/detail-788720.html
到了這里,關于SpringBoot高版本(2.4及以上)集成neo4j并進行增刪改查,通俗易懂附源代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!