Spring Data Neo4j

文章目录

  • Spring Data Neo4j简介
    • Neo4j-OGM与SDN的区别
  • 开发体验
    • 版本说明
    • 项目地址
    • 项目结构
    • 创建项目
    • 配置连接信息
    • 激活事务管理器
    • 创建实体类
      • Movie类
      • Person类
      • ActedIn关系类
    • 创建Dao层
    • service层
    • 测试案例
      • CRUD Test
      • PersonService Test
      • ActedIn Test
    • 执行结果查询

Spring Data Neo4j简介

  • Spring Data Neo4j官网学习地址
  • Spring Data Neo4j简称SDN,SDN建立在Neo4j OGM基础之上,使用SDN可以帮助简化OGM的使用,更加容易与Spring框架整合应用。
  • SDN 完全依赖于 Neo4j Java 驱动程序,而无需在映射框架和驱动程序之间引入另一个“驱动程序”或“传输”层。Neo4j Java 驱动程序(有时称为 Bolt 或 Bolt 驱动程序)用作协议,与 JDBC 用于关系数据库非常相似。
  • SDN 是一个对象图映射 (OGM) 库。OGM 将图形中的节点和关系映射到域模型中的对象和引用。对象实例映射到节点,而对象引用使用关系进行映射,或序列化为属性(例如,对 Date 的引用)。JVM 原语映射到节点或关系属性。OGM 抽象了数据库,并提供了一种便捷的方法,可以将域模型持久保存在图形中并对其进行查询,而无需直接使用低级驱动程序。它还为开发人员提供了灵活性,可以在 SDN 生成的查询不足的情况下提供自定义查询。
    在这里插入图片描述
  • 驱动程序用于连接数据库。包括三种连接方式:嵌入式、HTTP、和二进制Bolt。
  • Neo4j对象图映射器(neo4j-OGM)
  • Spring Data Neo4j在Neo4j-OGM上提供代码,帮助快速构建基于Spring的Neo4j应用程序。

Neo4j-OGM与SDN的区别

  • Spring Data Neo4i(SDN)使用Neo4j-OGM执行与数据库之间的映射。在Spring Data JPA的上下文中,可以将OGM与Hibernate之类的PA实现在同一级别上看待。

开发体验

版本说明

组件版本
Spring Boot3.4.2
neo4j5.26.1
IDEA2024.2.1
spring-data-neo4j7.4.2

项目地址

  • SpringAndNeo4j

项目结构

.
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── yang
│   │   │           └── stu
│   │   │               ├── StuApplication.java
│   │   │               ├── configuration
│   │   │               │   └── Neo4jConfiguration.java
│   │   │               ├── pojo
│   │   │               │   ├── ActedIn.java
│   │   │               │   ├── Movie.java
│   │   │               │   ├── Person.java
│   │   │               │   └── PersonInfo.java
│   │   │               ├── repository
│   │   │               │   ├── ActedRepository.java
│   │   │               │   ├── MovieRepository.java
│   │   │               │   └── PersonRepository.java
│   │   │               └── service
│   │   │                   └── PersonService.java
│   │   └── resources
│   │       └── application.properties
│   └── test
│       └── java
│           └── com
│               └── yang
│                   └── stu
│                       ├── ActedInRepositoryTest.java
│                       ├── PersonServiceTest.java
│                       └── StuApplicationTests.java

创建项目

在这里插入图片描述
在这里插入图片描述

配置连接信息

spring.application.name=Stu
spring.neo4j.uri=bolt://IP:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=neo4j
spring.neo4j.pool.max-connection-pool-size=1000
spring.neo4j.pool.max-connection-lifetime=2h
logging.level.org.springframework.data.neo4j=ERROR

激活事务管理器

import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;@Configuration
@EnableTransactionManagement //激活事务管理器
public class Neo4jConfiguration {}

创建实体类

Movie类

import lombok.*;
import org.springframework.data.neo4j.core.schema.*;import java.io.Serializable;
import java.util.List;@Node //spring-data-neo4j 7.4.2中使用Node注解标记实体类
@NoArgsConstructor
@ToString
@Data 
public class Movie implements Serializable {@Id@GeneratedValueprivate Long id;private String title;private Long released;@Property("tagline")private String tagLine;//设置关系并且指定方向@Relationship(type = "ACTED_IN",direction = Relationship.Direction.INCOMING)private List<ActedIn> actedIns;
}    

Person类

import lombok.*;
import org.springframework.data.neo4j.core.schema.*;
import java.io.Serializable;
import java.util.List;@Node
@Data
@ToString
public class Person implements Serializable {@Id@GeneratedValueprivate Long id;private String name;private Long born;private String sex;@Relationship(type = "ACTED_IN",direction = Relationship.Direction.OUTGOING)private List<ActedIn> actedIns;//导演关系@Relationship(type = "DIRECTED")private List<Movie> directedMovies;//出品关系@Relationship(type = "PRODUCED")private List<Movie> producedMovies;//写作关系@Relationship(type = "WROTE")private List<Movie> wroteMovies;
}

ActedIn关系类

  • 使用
import lombok.*;
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;@RelationshipProperties
@ToString(exclude = {"person","movie"})
@Data
public class ActedIn {@Id@GeneratedValueprivate Long id;//关系中的开始节点 自动推断不用注解private Person person;@TargetNode  //关系中的结束节点 使用注解TargetNodeprivate Movie movie;private String[] roles;
}    

创建Dao层

  • Repository 是一个重要的组件,用于定义与 Neo4j 数据库的交互。管理实体的 CRUD(创建、读取、更新、删除)操作。
  • Dao层的作用:
    • 数据访问层:Repository 作为一个接口,负责定义数据访问层,其中的方法通常与实体的数据库操作(例如存储、查找、更新和删除)相关联。
    • 自动化 CRUD 操作:通过继承 Neo4jRepository<ActedIn, Long>,XRepository 自动获得一些基本的 CRUD 方法,如 save(), findById(), delete(), 以及可以通过定义其他方法实现查询功能。
    • 自定义查询:除了继承基本的 CRUD 方法,还可以在 XRepository 中定义查询方法
  • @Repository 注解:这个注解表明这是一个 DAO(数据访问对象) 类;Spring 会自动识别这个类,并进行相关的异常转换。
import com.yang.stu.pojo.ActedIn;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ActedRepository extends Neo4jRepository<ActedIn,Long> {}
import com.yang.stu.pojo.Movie;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface MovieRepository extends Neo4jRepository<Movie, Long> {Movie findByTitle(String 西红柿首富);
}

import com.yang.stu.pojo.Person;
import com.yang.stu.pojo.PersonInfo;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;import java.util.List;@Repository
public interface PersonRepository extends Neo4jRepository<Person,Long> {Person findByName(String name);List<Person> findByNameContains(String tom);@Query("match (m:Movie) <-[:ACTED_IN]-(p) where m.title=$movieName return p")List<Person> findByMovie(@Param("movieName") String movieName);@Query("match (n:Person {name:$name})-[:ACTED_IN]->(x) return n.name as name,$year-n.born as age,collect(x) as movies")PersonInfo findAgeAndMovieCountByName(@Param("name") String name, @Param("year") Integer year);
}

service层

import com.yang.stu.pojo.Person;
import com.yang.stu.repository.PersonRepository;
import jakarta.annotation.Resource;
import jakarta.transaction.Transactional;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.Random;@Service
public class PersonService {@Resourceprivate PersonRepository personRepository;@Transactional //使用事务注解 确保操作的原子性public void addSexToAllPerson(){List<Person> personList = personRepository.findAll();String[] sexs = {"man", "woman"};for (Person person : personList) {person.setSex(sexs[new Random().nextInt(2)]);personRepository.save(person);}}
}

测试案例

CRUD Test

  • 普通的CRUD操作
@SpringBootTest
class StuApplicationTests {@Autowiredprivate PersonRepository personRepository;@Resourceprivate MovieRepository movieRepository;@Testpublic void existPersonById() {boolean exists = personRepository.existsById(34L);System.out.println(exists);}@Testpublic void queryPersonAll() {List<Person> personList = personRepository.findAll();personList.forEach(x-> System.out.println(x.toString()));}@Testpublic void queryPersonById() {Optional<Person> optionalPerson = personRepository.findById(34L);System.out.println(optionalPerson.get().getName());}@Testpublic void queryPersonByName() {String name = "Tom Hanks";  // 假设我们要查询的名字是“张三”Person person = personRepository.findByName(name);System.out.println(person);}@Testpublic void queryMovieById() {Optional<Movie> optionalMovie = movieRepository.findById(32L);System.out.println(optionalMovie.get().getTitle());}@Testpublic void findByNameContains() {List<Person> personList = personRepository.findByNameContains("Tom");personList.forEach(x-> System.out.println(x.toString()));}@Testpublic void testFindPage(){PageRequest pageRequest = PageRequest.of(0, 10, Sort.by(Sort.Order.asc("name")));Page<Person> page = personRepository.findAll(pageRequest);List<Person> personList = page.getContent();System.out.println("数据总量 :"+page.getTotalElements());System.out.println("总页数 :"+page.getTotalPages());personList.forEach(x-> System.out.println(x.toString()));}@Testpublic void fineActorsByMovieName(){List<Person> actors = personRepository.findByMovie("Johnny Mnemonic");actors.forEach(x-> System.out.println(x.toString()));}@Testpublic void findAgeAndMovieCountByName(){PersonInfo result = personRepository.findAgeAndMovieCountByName("Tom Hanks", 2025);System.out.println(result);}@Testpublic void savePerson(){Person person = new Person();person.setName("沈崇");person.setBorn(1980L);Person savedPerson = personRepository.save(person);System.out.println(savedPerson);}@Testpublic void SaveMovie(){Movie movie = new Movie();movie.setTitle("西红柿首富");movie.setReleased(2019L);movie.setTagLine("搞笑");Movie savedMovie = movieRepository.save(movie);System.out.println(savedMovie);}@Testpublic void findByName(){Movie movie = movieRepository.findByTitle("西红柿首富");System.out.println(movie);}@Testpublic void UpdataMovie(){Movie movie = movieRepository.findByTitle("西红柿首富");movie.setReleased(2018L); //更新值Movie saved = movieRepository.save(movie);System.out.println(saved);}/*** 根据id删除*/@Testpublic void deleteMovieById(){movieRepository.deleteById(32L);}/*** 根据实体删除*/@Testpublic void deleteMovieByTitle(){Movie movie = movieRepository.findByTitle("西红柿首富");movieRepository.delete(movie);}
}

PersonService Test

  • 测试PersonService添加性别的方法
@SpringBootTest
public class PersonServiceTest {@Resourceprivate PersonService personService;@Testpublic void testAddSex() {personService.addSexToAllPerson();}
}

ActedIn Test

  • 测试级联保存和批量保存
@SpringBootTest
public class ActedInRepositoryTest {@Resourceprivate PersonRepository personRepository;@Resourceprivate MovieRepository movieRepository;@Testpublic void saveActed() {// 查询 Person 和 Movie 节点Person person = personRepository.findByName("沈崇");Movie movie = movieRepository.findByTitle("西红柿首富");// 创建关系ActedIn actedIn = new ActedIn();actedIn.setPerson(person);actedIn.setMovie(movie);actedIn.setRoles(new String[]{"王多鱼"});// 将 ActedIn 添加到 Person 的关系列表中List<ActedIn> actedIns = person.getActedIns();actedIns.add(actedIn);person.setActedIns(actedIns);// 保存 Person,实现级联保存personRepository.save(person);}@Testpublic void saveAll(){Movie movie = movieRepository.findByTitle("西红柿首富");List<Person> personList=new ArrayList<>();Person person = new Person();person.setName("艾伦");person.setBorn(1981L);ActedIn actedIn = new ActedIn();actedIn.setPerson(person);actedIn.setMovie(movie);actedIn.setRoles(new String[]{"高然"});person.setActedIns(Arrays.asList(actedIn));personList.add(person);Person person2 = new Person();person2.setName("张一鸣");person2.setBorn(1986L);ActedIn actedIn2 = new ActedIn();actedIn2.setPerson(person2);actedIn2.setMovie(movie);actedIn2.setRoles(new String[]{"庄强"});person2.setActedIns(Arrays.asList(actedIn2));personList.add(person2);List<Person> saveAll = personRepository.saveAll(personList);saveAll.forEach(System.out::println);}
}

执行结果查询

  • 查看参演西红柿首富的演员
match (n:Person)-->(m:Movie) where m.title="西红柿首富" return *

在这里插入图片描述

  • 删除节点和关系
match (n:Movie)<-[r]-(m) where n.title="西红柿首富" delete m,r,n

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java发展史

JavaEE的由来 语言的诞生 Java的前身是Oak语言&#xff0c;其目的是搞嵌入式开发开发智能面包机 叮~~~&#x1f35e;&#x1f35e;&#x1f35e; 产品以失败告终 巅峰 网景公司需要网景浏览器打开网页&#xff0c;Oak->Java&#xff0c;进行前端开发&#xff08;相关技…

怎么让DeepSeek自动化写作文案

在数字化时代&#xff0c;内容创作已成为企业争夺用户注意力的核心竞争力。面对海量信息需求&#xff0c;企业往往面临内容创作效率低下、质量参差不齐、周期长等问题。如何用技术手段解决这些痛点&#xff0c;成为企业迫切需要破解的难题。今天&#xff0c;我们将以DeepSeek为…

Mysql之主从复制

目录 1.概述 2.工作原理 3.综合案例 3.1前期准备 3.2主库配置 3.3从库配置 3.4常见问题 3.4.1主从同步出现一下错误&#xff1a;Slave_IO_Running: No 3.4.1主从同步出现一下错误&#xff1a;Slave_IO_Running: Connecting? 3.5数据测试 1.概述 MySQL的主从复制&am…

从无序到有序:上北智信通过深度数据分析改善会议室资源配置

当前企业普遍面临会议室资源管理难题&#xff0c;预约机制不完善和临时会议多导致资源调度不合理&#xff0c;既有空置又有过度拥挤现象。 针对上述问题&#xff0c;上北智信采用了专业数据分析手段&#xff0c;巧妙融合楼层平面图、环形图、折线图和柱形图等多种可视化工具&a…

使用pyCharm创建Django项目

使用pyCharm创建Django项目 1. 创建Django项目虚拟环境&#xff08;最新版版本的Django) 使用pyCharm的创建项目功能&#xff0c;选择Django,直接创建。 2. 创建Django项目虚拟环境&#xff08;安装特定版本&#xff09; 2.1创建一个基础的python项目 2.2 安装指定版本的D…

RabbitMQ 在 Spring Boot中使用方式

文章目录 作用MQ docker 安装MQ使用RabbitMQ的整体架构及核心概念&#xff1a;RabbitMQ的整体架构及核心概念&#xff1a;消费者消息推送限制交换机与队列## 项目使用MQDirect: 直连模式Fanout: 广播模式Topic: 主题模式Headers: 头信息模式 使用DEMO地址异常问题记录 作用 Ra…

力扣动态规划-30【算法学习day.124】

前言 ###我做这类文章一个重要的目的还是记录自己的学习过程&#xff0c;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&#xff01;&#xff01;&#xff01; 习题 1.零钱兑换 题目链接:322. 零钱兑…

AI在电竞比分网中的主要应用场景

AI在电竞体育比分网的数据应用非常广泛&#xff0c;能够显著提升数据分析、预测、用户体验和商业价值。以下是AI在电竞比分网中的主要应用场景&#xff1a; 1. 实时数据采集与分析 比赛数据实时更新&#xff1a;AI通过自动化系统实时采集比赛数据&#xff08;如击杀数、经济差、…

【Spring Boot】Spring 魔法世界:Bean 作用域与生命周期的奇妙之旅

前言 ???本期讲解关于spring原理Bean的相关知识介绍~~~ ??感兴趣的小伙伴看一看小编主页&#xff1a;-CSDN博客 ?? 你的点赞就是小编不断更新的最大动力 ??那么废话不多说直接开整吧~~ 目录 ???1.Bean的作用域 ??1.1概念 ??1.2Bean的作用域 ??1.3代码演示…

用 Python 实现 DeepSeek R1 本地化部署

DeepSeek R1 以其出色的表现脱颖而出&#xff0c;不少朋友想将其本地化部署&#xff0c;网上基于 ollama 的部署方式有很多&#xff0c;但今天我要带你领略一种全新的方法 —— 使用 Python 实现 DeepSeek R1 本地化部署&#xff0c;让你轻松掌握&#xff0c;打造属于自己的 AI…

软考-系统架构设计师(月更版)

1.需求管理的主要活动包括变更控制&#xff0c;版本控制&#xff0c;需求跟踪&#xff0c;需求状态跟踪 需求跟踪是单个需求和其他系统元素之间的依赖关系和逻辑联系建跟踪&#xff0c; 这些元素包括各种类型的需求、业务规则、系统架构和构件、源代码、测试用例&#xff0c;以…

IOTDB安装部署

IOTDB一般用于工业互联网&#xff0c;至于具体的介绍请自行搜索 1.环境准备 安装前需要保证设备上配有 JDK>1.8 的运行环境&#xff0c;并配置好 JAVA_HOME 环境变量。 设置最大文件打开数为 65535。 关闭防火墙 systemctl stop firewalld.service systemctl disable …

分享 UniApp 实现列表长按删除功能

在移动应用开发中&#xff0c;列表是常见的展示形式&#xff0c;而长按删除列表项也是一个实用且常见的交互功能。今天就来和大家分享如何在 UniApp 中实现列表的长按删除功能&#xff0c;同时附上详细的代码。 效果预览 通过代码实现后&#xff0c;我们将得到一个带有红色边…

leetcode 2684. 矩阵中移动的最大次数

题目如下 数据范围 本题使用常规动态规划就行&#xff0c;不过要注意由于有三个转移的方向&#xff0c;所以我们对dp数组的遍历应该是从上到下 从左到右即按列优先遍历。通过代码 class Solution { public:int maxMoves(vector<vector<int>>& grid) {int …

深入剖析 Burp Suite:Web 应用安全测试利器

目录 前言 一、Burp Suite 简介 二、功能组件详解 三、使用场景 四、安装与使用步骤 安装步骤 使用步骤 五、总结 前言 在网络安全的复杂版图中&#xff0c;Burp Suite 宛如一颗璀璨的明珠&#xff0c;以其强大的功能和广泛的适用性&#xff0c;成为众多安全从业者不可…

linux内网部署deepseek大模型(ollama+anythingllm)

一、安装ollama 来源&#xff1a;ollama/docs/linux.md at main ollama/ollama GitHub 1.下载安装包 ollama下载链接&#xff1a;https://ollama.com/download/ollama-linux-amd64.tgz&#xff0c;下载后放在用户目录下 2.运行脚本 #!/bin/sh # This script installs Olla…

【学术投稿-第四届智能电网和绿色能源国际学术会议(ICSGGE 2025)】CSS基本选择器详解:掌握基础,轻松布局网页

可线上 官网&#xff1a;www.icsgge.org 时间&#xff1a;2025年2月28-3月2日 目录 前言 一、基本选择器简介 1. 元素选择器&#xff08;Type Selector&#xff09; 基本语法 示例 注意事项 2. 类选择器&#xff08;Class Selector&#xff09; 基本语法 示例 注意…

聊聊 IP 地址和端口号的区别

在计算机网络中&#xff0c;两个基本概念对于理解设备如何通过网络进行通信至关重要。IP 地址和端口号是 TCP/IP 的典型特征&#xff0c;其定义如下&#xff1a;IP 地址是分配给连接到网络的每台机器的唯一地址&#xff0c;用于定位机器并与其通信。相反&#xff0c;端口号用于…

【个人开发】cuda12.6安装vllm安装实践【内含踩坑经验】

1. 背景 vLLM是一个快速且易于使用的LLM推理和服务库。企业级应用比较普遍&#xff0c;尝试安装相关环境&#xff0c;尝试使用。 2. 环境 模块版本python3.10CUDA12.6torch2.5.1xformers0.0.28.post3flash_attn2.7.4vllm0.6.4.post1 2.1 安装flash_attn 具体选择什么版本&…

问界M8细节曝光,L3自动驾驶有了!

文 | AUTO芯球 作者 | 雷慢 太惊喜了&#xff0c; 问界M8近距离实拍曝光了&#xff0c; 我看了一圈&#xff0c; 给大家扒出几个炸裂的信息&#xff0c; 注意看侧身这一堆传感器&#xff0c; 这可不是什么普通摄像头&#xff0c; 这一片传感器和和尊界S800那套一模一样&a…