当前位置: 首页 > news >正文

SpringBoot该怎么使用Neo4j - 优化篇

文章目录

  • 前言
  • 实体工具
  • 使用

前言

上一篇中,我们的Cypher都用的是字符串,字符串拼接简单,但存在写错的风险,对于一些比较懒的开发者,甚至觉得之间写字符串还更自在快速,也确实,但如果在后期需要修改,如更高字段名或者一些级联的变动,会导致维护难,所以,这里这里我们模仿Mybatis-Plus写一个实体字段工具之间替换哪些字符串,以提高项目可维护性。
如需要了解上篇,位置:SpringBoot该怎么使用Neo4j

实体工具

我们以这篇的工具为基础进行下面的开发:Lambda表达式提取字段名-CSDN博客

然后我们再增加对于与Neo4j的实体工具:

  1. 实体缓存对象信息,保存实体必要信息

    public class EntityCache {private String className;private List<String> labels;private Map<String, String> fieldNameMap;public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}public List<String> getLabels() {return labels;}public void setLabels(List<String> labels) {this.labels = labels;}public Map<String, String> getFieldNameMap() {return fieldNameMap;}public void setFieldNameMap(Map<String, String> fieldNameMap) {this.fieldNameMap = fieldNameMap;}
    }
  2. 解析工具,也就是反射解析

    public class EntityUtil {/*** 实体缓存*/private static final Map<String, EntityCache> ENTITY_MAP = new ConcurrentHashMap<>();public static void main(String[] args) {Job job = new Job();String column = column(Job::getName);System.out.println(column);System.out.println(label(Job.class));}/*** 从lambda转换出字段名*/public static <T, R> String column(CusFunction<T, R> column) {SerializedLambda resolve = LambdaUtils.resolve(column);return getColumn(LambdaUtils.getClass(resolve), LambdaUtils.getMethodName(resolve) , true);}/*** 从实体class解析出标签*/public static <T> String label(Class<T> clazz) {EntityCache info = ENTITY_MAP.putIfAbsent(clazz.getTypeName(), resolve(clazz));return info.getLabels().get(0);}/*** 根据类型和方法名解析字段名* @param aClass 类型* @param methodName 方法名* @param dbField 是否数据库字段* @return 字段名*/private static String getColumn(Class<?> aClass, String methodName, boolean dbField) {String fieldName = PropertyNamer.methodToProperty(methodName);if (!dbField) {return fieldName;}EntityCache info = resolve(aClass);if (!StringUtils.hasLength(fieldName)) {throw new RuntimeException(String.format("找不到实体对应的字段-[%s.%s]", aClass.getTypeName(), methodName));}Map<String, String> map = info.getFieldNameMap();return map.get(fieldName);}/*** 解析实体* @param clazz 类型* @return 实体缓存对象*/public static <T> EntityCache resolve(Class<T> clazz) {String typeName = clazz.getTypeName();EntityCache info = ENTITY_MAP.get(typeName);if (info != null) {return info;}Field[] declaredFields = clazz.getDeclaredFields();Map<String, String> fieldNameMap = new HashMap<>();for (Field declaredField : declaredFields) {declaredField.setAccessible(true);String fieldName = declaredField.getName();String dbFieldName = fieldName;Property property = declaredField.getAnnotation(Property.class);if (property != null) {if (StringUtils.hasLength(property.name())) {dbFieldName = property.name();}if (StringUtils.hasLength(property.value())) {dbFieldName = property.value();}}fieldNameMap.put(fieldName, dbFieldName);}List<String> labelList = resolveLabel(clazz);info = new EntityCache();info.setLabels(labelList);info.setClassName(typeName);info.setFieldNameMap(fieldNameMap);ENTITY_MAP.put(typeName, info);return info;}/*** 解析标签* @param clazz 类型* @return 标签列表*/private static <T> List<String> resolveLabel(Class<T> clazz) {Node node = clazz.getAnnotation(Node.class);if (node == null) {throw new RuntimeException("非数据库实体对象实体!");}String[] value = node.value();String[] labels = node.labels();List<String> result = new ArrayList<>();result.addAll(Arrays.asList(value));result.addAll(Arrays.asList(labels));if (result.isEmpty()) {result.add(clazz.getSimpleName());}return result;}
    }
  3. 测试:

        @Testpublic void testEntity() {String column = EntityUtil.column(Job::getName);EntityUtil.label(Job.class);String column1 = EntityUtil.column(Job::getJobName);System.out.println(column +"  " + column1);}
    

使用

实际开发中,就可以将字符串进行替换,如下面:

查询标签Jobname='liry',并通过id顺序排序,取第一个的cypher构建

// match(a:Job) where a.name='liry' return a order by a.id  limit 1Node temp = Cypher.node("Job").named("a");
ResultStatement statement = Cypher.match(temp).where(temp.property("name").isEqualTo(Cypher.anonParameter(job.getName()))).returning(temp.getRequiredSymbolicName()).orderBy(temp.property("id")).limit(1).build();

进行替换

// match(a:Job) where a.name='liry' return a order by a.id  limit 1// 字符串 Job  -> EntityUtil.label(Job.class)
// 字符串 name -> EntityUtil.column(Job::getName)
// 字符串 id -> EntityUtil.column(Job::getId)
Node temp = Cypher.node(EntityUtil.label(Job.class)).named("a");
ResultStatement statement = Cypher.match(temp).where(temp.property(EntityUtil.column(Job::getName)).isEqualTo(Cypher.anonParameter(job.getName()))).returning(temp.getRequiredSymbolicName()).orderBy(temp.property(EntityUtil.column(Job::getId))).limit(1).build();

创建一个节点:

create (a:Job{name:'liry',jobName:'liry-job'}) return a;          

可以看到调试中构建的Cypher是正确的。

image-20241204181636501

相关文章:

SpringBoot该怎么使用Neo4j - 优化篇

文章目录 前言实体工具使用 前言 上一篇中&#xff0c;我们的Cypher都用的是字符串&#xff0c;字符串拼接简单&#xff0c;但存在写错的风险&#xff0c;对于一些比较懒的开发者&#xff0c;甚至觉得之间写字符串还更自在快速&#xff0c;也确实&#xff0c;但如果在后期需要…...

Flutter如何调用java接口如何导入java包

文章目录 1. Flutter 能直接调用 Java 的接口吗&#xff1f;如何调用 Java 接口&#xff1f; 2. Flutter 能导入 Java 的包吗&#xff1f;步骤&#xff1a; 总结 在 Flutter 中&#xff0c;虽然 Dart 是主要的开发语言&#xff0c;但你可以通过**平台通道&#xff08;Platform …...

Redis 数据结构(一)—字符串、哈希表、列表

Redis&#xff08;版本7.0&#xff09;的数据结构主要包括字符串&#xff08;String&#xff09;、哈希表&#xff08;Hash&#xff09;、列表&#xff08;List&#xff09;、集合&#xff08;Set&#xff09;、有序集合&#xff08;Sorted Set&#xff09;、超日志&#xff08…...

day1:ansible

ansible-doc <module_name>&#xff08;如果没有网&#xff0c;那这个超级有用&#xff09; 这个很有用&#xff0c;用来查单个模块的文档。 ansible-doc -l 列出所有模块 ansible-doc -s <module_name> 查看更详细的模块文档。 ansible-doc --help 使用 --help …...

如何设置Java爬虫的异常处理?

在Java爬虫中设置异常处理是非常重要的&#xff0c;因为网络请求可能会遇到各种问题&#xff0c;如连接超时、服务器错误、网络中断等。通过合理的异常处理&#xff0c;可以确保爬虫的稳定性和健壮性。以下是如何在Java爬虫中设置异常处理的步骤和最佳实践&#xff1a; 1. 使用…...

阿里云盘permission denied

问题是执行 ./aliyunpan 时遇到了 Permission denied 的错误。这通常是因为文件没有执行权限。以下是解决问题的步骤&#xff1a; 检查文件权限 运行以下命令检查文件的权限&#xff1a; ls -l aliyunpan输出中会看到类似以下内容&#xff1a; -rw-r--r-- 1 user group 123…...

在 Ubuntu 24 上安装 Redis 7.0.15 并配置允许所有 IP 访问

前提条件 一台运行 Ubuntu 24 的服务器拥有 sudo 权限的用户 步骤一&#xff1a;更新系统包 首先&#xff0c;确保系统包是最新的&#xff0c;以避免潜在的依赖问题。 sudo apt update sudo apt upgrade -y步骤二&#xff1a;安装编译 Redis 所需的依赖 Redis 需要一些编译…...

构建高效可靠的分布式推理系统:深入解析控制器与模型服务的协同工作

在现代互联网应用中,随着用户需求的增长和技术的进步,单一服务器已经难以满足大规模并发请求的需求。为了提升系统的性能和可靠性,开发者们越来越多地采用分布式架构。本文将结合具体的代码示例,深入浅出地探讨如何构建一个高效的分布式推理系统,并详细解析其中的关键组件…...

springboot394疫情居家办公系统(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统疫情居家办公系统信息管理难度大&#xff0c;容错率低&a…...

共筑数字安全防线,2024开源和软件安全沙龙即将启幕

随着数字化转型进程的加快以及开源代码的广泛应用&#xff0c;开源凭借平等、开放、协作、共享的优秀创作模式&#xff0c;逐渐成为推动数字技术创新、加速传统行业转型升级的重要模式。但随着软件供应链日趋复杂多元&#xff0c;使得其安全风险不断加剧&#xff0c;针对软件供…...

后端报错: message: “For input string: \“\““

这个错误信息表明后端尝试将一个空字符串 "" 转换为某种数值类型&#xff08;如整数、长整型等&#xff09;&#xff0c;但转换失败了。在许多编程语言中&#xff0c;如果你试图解析一个非数字的字符串&#xff08;在这个情况下是一个空字符串&#xff09;为数值类型…...

39 矩阵置零

39 矩阵置零 39.1 矩阵置零解决方案 解题思路&#xff1a; 利用第一行和第一列标记&#xff1a; 使用两个标记变量&#xff0c;rowZero和colZero&#xff0c;来判断第一行和第一列是否需要置零。遍历矩阵从(1,1)开始&#xff0c;如果某个元素是0&#xff0c;则标记该行和该列…...

使用伪装IP地址和MAC地址进行Nmap扫描

使用伪装IP地址和MAC地址进行Nmap扫描 在某些网络设置中&#xff0c;攻击者可以使用伪装的IP地址甚至伪装的MAC地址进行系统扫描。这种扫描方式只有在可以保证捕获响应的情况下才有意义。如果从某个随机的网络尝试使用伪装的IP地址进行扫描&#xff0c;很可能无法接收到任何响…...

linux安装docker和mysql

1.下载安装doker 1. 更新系统,确保系统是最新的 sudo yum update -y2.安装 Docker 所需的依赖包&#xff1a; sudo yum install -y yum-utils 2. 设置 Docker 仓库 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 3. 安装 Dock…...

贪心算法专题(四)

目录 1. 单调递增的数字 1.1 算法原理 1.2 算法代码 2. 坏了的计算器 2.1 算法原理 2.2 算法代码 3. 合并区间 3.1 算法原理 3.2 算法代码 4. 无重叠区间 4.1 算法原理 4.2 算法代码 5. 用最少数量的箭引爆气球 5.1 算法原理 ​5.2 算法代码 1. 单调递增的数字…...

QT 多级嵌套结构体,遍历成员--半自动。<模板+宏定义>QTreeWidget树结构显示

Qt的QTreeWidget来显示嵌套结构体的成员&#xff0c;并以树形结构展示。 #include <QApplication> #include <QTreeWidget> #include <QTreeWidgetItem> #include <QString> #include <cstdint>// 假设这些是你的结构体定义 struct BaseMeterPa…...

NLP-中文分词

中文分词 1、中文分词研究背景及意义 和大部分西方语言不同&#xff0c;书面汉语的词语之间没有明显的空格标记&#xff0c;句子是以字串的形式出现。因此对中文进行处理的第一步就是进行自动分词&#xff0c;即将字串转变成词串。 比如“中国建筑业呈现新格局”分词后的词串…...

详解LeetCode地下城游戏(动态规划)——区分两种状态表示形式

地下城游戏 题目链接&#xff1a;174. 地下城游戏 状态表示&#xff1a; 按照以往题的表示&#xff0c;dp[i][j]表示&#xff1a;从起点&#xff08;0&#xff0c;0&#xff09;位置到达&#xff08;i&#xff0c;j&#xff09;位置时&#xff0c;所需的最小初始健康值。但是…...

.NET正则表达式

正则表达式提供了功能强大、灵活而又高效的方法来处理文本。 正则表达式丰富的泛模式匹配表示法使你可以快速分析大量文本&#xff0c;以便&#xff1a; 查找特定字符模式。 验证文本以确保它匹配预定义模式&#xff08;如电子邮件地址&#xff09;。 提取、编辑、替换或删除…...

k8s 为什么需要Pod?

Pod&#xff0c;是 Kubernetes 项目中最小的 API 对象&#xff0c;更加专业的说&#xff0c;Pod&#xff0c;是 Kubernetes 项目的原子调度单位。 Pod 是 Kubernetes 里的原子调度单位。这就意味着&#xff0c;Kubernetes 项目的调度器&#xff0c;是统一按照 Pod 而非容器的资…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...