图数据库Neo4j学习四——Spring Data NEO

news2024/9/8 23:41:07

1配置

1.1Maven依赖

<!--neo4j  -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>

1.2yml配置

spring:
  data:
    neo4j:
      uri: bolt://localhost:7687
      username: neo4j
      password: 123456
      database: neo4j

1.3neo扫包

@SpringBootConfiguration
@EnableNeo4jRepositories(basePackages = "com.**.repo")
public class NeoConfig {

}

2入门代码

2.1代码结构

在这里插入图片描述

2.2node

如下所示,这是我们的一个实际的节点,我们以该节点为例,创建一个UserNode
在这里插入图片描述

//如果你没有使用lombook,请自己手动生成对应的get/set
@Data
@NodeEntity("User")
public class UserNode {
    @Id
    @GeneratedValue
    private Long id;
    private String userName;
    private int userAge;
    private String userSex;
}

2.3repo

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

}

2.4service

public interface UserService {

	void saveUser(UserNode userNode);
	
	UserNode getUserById(Long id);
}

@Service
public class UserServiceImpl implements UserService{

	@Autowired
    private UserRepository userRepository;

	@Override
    public void saveUser(UserNode userNode) {
    	userRepository.save(userNode);
    }
	
	@Override
    public UserNode getUserById(Long id) {
    	return userRepository.findById(id).orElse(null);
    }
	
}

2.5controller

@RestController
public class UserController {
	
    @Autowired
    private UserService userService;

    @PostMapping("/user")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "新增用户节点")
    public R<String> savePerson(@RequestBody UserNode userNode) {
    	userService.saveUser(userNode);
    	return R.ok();
    }
    


    @GetMapping("/user/id{id}")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "根据ID获取用户节点")
    public R<UserNode> getUserById(@PathVariable Long id) {
    	UserNode user = userService.getUserById(id);
    	return R.ok(user);
    }
}

如果出现以下错误

The client is unauthorized due to authentication failure.

解决方法:找到你安装neo4j的路径下的conf文件夹,neo4j.conf,找到

#dbms.security.auth_enabled=false

将前面的注释#去掉,然后重启neo4j,在重启项目即可。
在这里插入图片描述

2.6验证

通过接口创建User节点,老王 ,然后再neo4j中查询,看能否查到
在这里插入图片描述
根据上面neo4j为我们生成的ID,使用这个ID进行查询,看能否查询到数据

在这里插入图片描述

3spring data neo详解

3.1节点

下面是我们实体类节点中常用的注解。

//表明这个类和节点进行映射
@NodeEntity

//节点的主键ID
@Id

//如果ID为null,生成默认的ID值
@GeneratedValue

//节点的关系
@Relationship
/*
Relationship.UNDIRECTED关系的起点和终点之间没有方向性
Relationship.OUTGOING 表示关系只能从起点指向终点(默认值)
Relationship.INCOMING 表示关系只能从终点指向起点
*/

//表明这个类和关系进行映射
@RelationshipEntity

//开始节点
@StartNode

//结束节点
@EndNode

接下来我们看一个例子。

我们定义了一个UserNode类和User标签节点进行映射,并且,该用户和其他用户存在RELATION的关系

@Data
@NodeEntity("User")
public class UserNode {
    @Id
    @GeneratedValue
    private Long id;
    private String userName;
    private int userAge;
    private String userSex;
    
    //和当前这个用户有关系的用户
    @Relationship(type = "RELATION")
    private List<UserNode> userNodes;
}

现在我们要实现,根据西子找出关系为RELATION的User节点
在这里插入图片描述
使用我们之前的接口,根据西子的id,查询西子信息即可
在这里插入图片描述
如果我们使用无向的关系,如下所示,就会出现循环嵌套(西子->老司->西子->老司),然后堆栈溢出。

@Relationship(type = "RELATION", direction = Relationship.UNDIRECTED)
private List<UserNode> userNodes;

在这里插入图片描述
如果我们使用反向的关系,那么根据西子查询,就查询不到了,但是根据念念,能查到西子和老司,因为西子和老司都指向念念,此时关系是逆向的,从终点到起点进行匹配。

@Relationship(type = "RELATION", direction = Relationship.INCOMING)
private List<UserNode> userNodes;

在这里插入图片描述

3.2Neo4jRepository

加粗样式还记得上面我们的入门案例嘛,我们编写了一个UserRepository来继承了Neo4jRepository,然而我们却没有任何的实现,这是因为Neo4jRepository默认提供了一些常用的方法来满足我们的增删查改

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

}

在这里插入图片描述
使用save方法将实体对象保存到Neo4j数据库中。

  1. 如果实体对象的ID为空,则新建一个节点并将实体对象保存到该节点上;
  2. 如果实体对象的ID不为空,则更新该节点的属性值。
<S extends T> S save(S entity);

<S extends T> S save(S s, int depth);

<S extends T> Iterable<S> save(Iterable<S> ses, int depth);

<S extends T> Iterable<S> saveAll(Iterable<S> entities);

因此当我们定义主键id,尽量使用包装类型,比如如果你的主键id设置为数字的,那么不要使用基本数据类型的int、long,而是使用包装类型的Integer、Long,并且最好是建议将新增和修改的UserNode拆成两个,在新增的时候没有属性id,在修改的时候有属性id,防止在新增的时候误传了id,变成修改操作。当然你也可通过其他方式,来进行区分新增或者更新,然后再新增的时候,将id设置为null。

那么S save(S entity)和S save(S s, int depth)有什么区别?

我们先看如下这个关系

@Data
@NodeEntity("User")
public class UserNode {
    @Id
    @GeneratedValue
    private Long id;
    private String userName;
    private int userAge;
    private String userSex;
    
    //和当前这个用户有关系的用户
    @Relationship(type = "老公", direction = Relationship.OUTGOING)
    private UserNode husband;
    
    @Relationship(type = "同事", direction = Relationship.OUTGOING)
    private UserNode colleague;
}

match(u1:User{userName:"西子"})-[f1:老公]->(u2)-[f2:同事]->(u3) return u1,u2,u3

在这里插入图片描述
在这里插入图片描述
可以看到现在西子18岁,小跟班12岁,孙悟空无年龄

UserNode 西子 = userRepository.findByUserName("西子").get(0);
//将西子和西子老公小跟班的年龄都设置为15岁
西子.setUserAge(15);
西子.getHusband().setUserAge(15);
    	
//Neo4jRepository 只能查询直接关联,因此查询不到小跟班的同事孙悟空
UserNode 孙悟空 = userRepository.findByUserName("孙悟空").get(0);
孙悟空.setUserAge(15);
西子.getHusband().setColleague(孙悟空);
    	
//我们这里将西子、小跟班、孙悟空的年龄都修改为18岁,然后只保存西子
userRepository.save(西子);

我们发现结果中,我们虽然只保存西子这个节点,但是西子的子节点,以及子节点的子节点都会被保存00.

在这里插入图片描述
现在我们使用S save(S s, int depth),先设置为0,发现只保存西子,没有保存小跟班和孙悟空

西子.setUserAge(18);
西子.getHusband().setUserAge(18);
孙悟空.setUserAge(18);

userRepository.save(西子, 0);

在这里插入图片描述

<S extends T> S save(S entity); //会将关联到的子节点,甚至子节点的子节点也会保存

<S extends T> S save(S s, int depth); //按照深度保存,0代表不保存子节点,1代表保存1级子节点

3.3自定义查询


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/816236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【机器学习】Cost Function for Logistic Regression

Cost Function for Logistic Regression 1. 平方差能否用于逻辑回归&#xff1f;2. 逻辑损失函数loss3. 损失函数cost附录 导入所需的库 import numpy as np %matplotlib widget import matplotlib.pyplot as plt from plt_logistic_loss import plt_logistic_cost, plt_two_…

利用易查分制作分班查询系统,怎么导入数据?

暑假过半&#xff0c;新学期即将到来&#xff0c;这对学校来说是一个重要的时刻。新学期的开始意味着学校将面临新生入学和老生升入高年级的情况&#xff0c;这就需要进行分班工作的安排。分班工作是一项繁琐而关键的任务&#xff0c;它直接关系到学生们在新学期中的班级和同学…

【Linux进程篇】进程概念(1)

【Linux进程篇】进程概念&#xff08;1&#xff09; 目录 【Linux进程篇】进程概念&#xff08;1&#xff09;进程基本概念描述进程-PCBtask_struct-PCB的一种task_ struct内容分类 组织进程查看进程通过系统调用获取进程标示符通过系统调用创建进程——fork初识 作者&#xff…

SpringMVC源码分析 —— 拦截器是何时调用的

SpringMVC源码分析&#xff0c;拦截器是何时、以什么方式调用的&#xff1f;本文将进行详细说明 环境准备 springboot 2.3.7.RELEASE 笔者创建一个springboot的web项目&#xff0c;使用的springboot的版本是2.3.7.RELEASE 对应的spring-web版本是5.2.12.RELEASE 下面将对上面…

【NLP-新工具】语音转文本与OpenAI的用途

一、说明 OpenAI最近2022发布了一个名为Whisper的新语音识别模型。与DALLE-2和GPT-3不同&#xff0c;Whisper是一个免费的开源模型。它的主要功能就是将语音翻译成文本。本文将介绍如何使用这个重要应用库。 二、 Whisper概念 2.1 Whisper是啥&#xff1f; Whisper 是一种自动…

考完软考,有什么备考心得和学习经验可以分享吗?

恭&#xfffd;&#xfffd;您完成软考考试&#xff01;备考软考确实是一项艰苦的任务&#xff0c;但也是一次很有收获的学习和成长过程。下面分享一些备考心得和学习经验&#xff0c;以及针对系统集成项目管理工程师和信息系统项目管理师考试的备考建议&#xff1a; 备考心得…

PACS系统源码:支持三维重建功能、集成放射科管理RIS系统、图文报告编辑、打印、多级审核机制

PACS系统源码 PACS系统是以最新的IT技术为基础&#xff0c;遵循医疗卫生行业IHE/DICOM3.0和HL7标准&#xff0c;开发的多功能服务器和阅片系统。通过简单高性能的阅片功能&#xff0c;支持繁忙时的影像诊断业务&#xff0c;拥有保存影像的院内Web传输及离线影像等功能&#xf…

【Android】APP网络优化学习笔记

网络优化原因 进行网络优化对于移动应用程序而言非常重要&#xff0c;原因如下&#xff1a; 用户体验&#xff1a; 网络连接是移动应用程序的核心功能之一。通过进行网络优化&#xff0c;可以提高应用的加载速度和响应速度&#xff0c;减少用户等待时间&#xff0c;提供更流…

跨境电商还有人在做吗,这十大选品技巧建议收藏!

随着电商的快速发展&#xff0c;无论国内或者国外电商&#xff0c;竞争都比较激烈&#xff0c;很多人觉得现在入行太晚了&#xff0c;玩不过那些老卖家。 不过我想说的是&#xff1a;做电商很重要的一点就是选品&#xff0c;那些很早一批老卖家可能也是借着红利期走过来的&…

ATFX汇市:美联储加息25基点,虽提振美指,或招致衰退

环球汇市行情摘要—— 上周&#xff0c;美元指数上涨0.6%&#xff0c;收盘在101.7点&#xff0c; 欧元贬值0.96%&#xff0c;收盘价1.1017点&#xff1b; 日元升值0.47%&#xff0c;收盘价141.16点&#xff1b; 英镑贬值0.01%&#xff0c;收盘价1.2852点&#xff1b; 瑞郎…

微信小程序配置上传多个u-upload上传

微信小程序配置上传多个u-upload上传 使用的是uView框架 微信小程序配置上传多个u-upload上传图片 场景需求&#xff1a;根据PC端配置项追加图片配置 小程序根据配置的图片数量&#xff0c;图片名称&#xff0c;进行上传图片 难度在于 我们不知道用户会追加多少个图片配置字段 …

预测性维护和预防性维护的区别

预测性维护和预防性维护是两种不同的设备维护策略&#xff0c;它们在维护时机、方法和效果上存在明显的区别。在工业生产和设备管理中&#xff0c;选择适合的维护方式对于提高设备的可靠性、延长寿命以及降低维护成本至关重要。本文将深入探讨预测性维护和预防性维护的区别及其…

【LeetCode】剑指offer礼物的最大价值

礼物的最大价值 题目描述算法分析编程代码 链接: 礼物的最大价值 题目描述 算法分析 编程代码 class Solution { public:int maxValue(vector<vector<int>>& grid) {int m grid.size();int n grid[0].size();vector<vector<int>> dp(m1,vector…

开利网络受邀参与战略合作伙伴和合控股 聚焦数据价值

近日&#xff0c;开利网络战略合作伙伴和合控股组织的“数据聚焦价值&#xff0c;引导数据化转型”主体研讨会&#xff0c;开利网络作为和合控股的战略合作伙伴和“数利丰”应用技术合作方&#xff0c;受邀进行落地应用分享。 随着“数字中国”战略的提出&#xff0c;数据已然成…

【爬虫逆向案例】某易云音乐(评论)js逆向—— params、encSecKey解密

声明&#xff1a;本文只作学习研究&#xff0c;禁止用于非法用途&#xff0c;否则后果自负&#xff0c;如有侵权&#xff0c;请告知删除&#xff0c;谢谢&#xff01; 【爬虫逆向案例】某易云音乐&#xff08;评论&#xff09;js逆向—— params、encSecKey解密 1、前言2、行动…

day57|● 647. 回文子串 ● 516.最长回文子序列

647. 回文子串 https://leetcode.cn/problems/palindromic-substrings/solution/by-lfool-2mvg/ Given a string s, return the number of palindromic substrings in it. A string is a palindrome when it reads the same backward as forward. A substring is a contiguous…

【Spring事务学习】事务分类 隔离级别 事务传播机制

目录 需要知道&#xff1a; &#x1f351;1、什么是事务&#xff1f; &#x1f351;2、事务的主要操作3个 一、Spring中事务的实现方式 &#x1f351;1、编程式事务&#xff08;手动写代码操作事务&#xff09;&#xff08;了解&#xff09; &#x1f351;2、声明式事务&…

【模型预测控制MPC】使用离散、连续、线性或非线性模型对预测控制进行建模(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

营销服一体化CRM有哪些?5款CRM系统对比

如今&#xff0c;一个成熟的CRM产品体系已从过去单点销售管理转变为营销、服务、交易的客户全旅程覆盖。那么在这个互联网信息化时代&#xff0c;面对海量的信息&#xff0c;用户很难快速准确地找到属于自己感兴趣的内容的&#xff0c;所以用户画像、兴趣标签变得越来越重要。 …

TCP三次握手和四次挥手以及11种状态(二)

11种状态 1、一开始&#xff0c;建立连接之前服务器和客户端的状态都为CLOSED&#xff1b; 2、服务器创建socket后开始监听&#xff0c;变为LISTEN状态&#xff1b; 3、客户端请求建立连接&#xff0c;向服务器发送SYN报文&#xff0c;客户端的状态变味SYN_SENT&#xff1b; 4、…