后端之JPA(EntityGraph+JsonView)
不同表之间的级联操作或者说关联查询是很多业务场景都会用到的。
对于这种需求最朴素的方法自然是手动写关联表,然后对被关联的表也是手动插入数据。但是手写容易最后写成一堆shit代码,而且修改起来也是非常麻烦的。
学会使用现成的工具还是非常有利的。接下来就来说一说JPA如何关联查询和实现级联操作。
@JsonManagedReference和@JsonBackReference
这两个注解配套使用,一般用在一对多关系,也就是外键级联操作。
在注解@OneToMany和@ManyToOne的基础上,一是用@JsonManagedReference,多用@JsonBackReference。同时也可以搭配其他的设置,如cascade和orphanRemoval来实现级联操作。
下面为一个示例
@Entity
@Data
@Table(name="math_questions")
public class Question {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@OneToMany(mappedBy = "question", cascade = CascadeType.ALL, orphanRemoval = true)@JsonManagedReference("question-questionTags") // 指定唯一的引用名称private List<QuestionTag> questionTags = new ArrayList<>();
}
@Entity
@Data
@Table(name="tags")
public class Tag {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@OneToMany(mappedBy = "tag", cascade = CascadeType.ALL, orphanRemoval = true)@JsonManagedReference("tag-questionTags") // 指定唯一的引用名称private List<QuestionTag> questionTags = new ArrayList<>();
}
@Entity
@Data
@Table(name = "question_tag")
public class QuestionTag {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id; // 主键@ManyToOne@JoinColumn(name = "question_id")@JsonBackReference("question-questionTags") // 与 Question 中的 @JsonManagedReference 对应private Question question;@ManyToOne@JoinColumn(name = "tag_id")@JsonBackReference("tag-questionTags") // 与 Tag 中的 @JsonManagedReference 对应private Tag tag;
}
那为什么要用到这两个注解呢?直接使用@OneToMany和@ManyToOne不就可以实现级联操作了吗?原因是我这里用的是双向关联,也就是Question中有Question_tag,Tags中有Question_tag,而Question_tag中又有Question和Tags。这样就会导致查询的时候无限递归下去,查到任何一个都可以继续级联查下去。
所以使用@JsonManagedReference和@JsonBackReference可以做到只查一层,也就是对Question表操作,只会影响question_tag表。同样对tags表操作,也只会影响question_tag表。这样就不会一直递归下去。
@EntityGraph
但是这样在之后又遇到一个问题,那就是在使用@EntityGraph进行关联查询的时候,发现只能从question查询到question_tag,再往下就查询不到了,实际上也是查询到了,只不过是因为又@JsonManagedReference和@JsonBackReference导致在最后被过滤掉了。
于是我就在想,有没有一种办法,即能保证不无限递归下去,又能做到查询到我想要的结果:通过question查询到与之相关的标签?
@JsonIdentityInfo
之后发现用@JsonIdentityInfo可以在查询到无限递归时自动停下来。乍一听似乎很好,但实际操作结果是,可能会有很多层嵌套,只能说最后结果对了,但是基本不可操作。
{"id": 17,"questionType": "LATEX","questionImagePath": null,"questionLatex": "测试添加标签","answerType": "BOTH","answerImagePath": "images/42f8099e-00ef-4485-a833-65541cb9b0d8_S2的配置命令.png","answerLatex": "1","uploadTime": "2025-02-24 11:25:41","lastPracticeTime": null,"correctCount": 0,"incorrectCount": 0,"questionTags": [{"id": 1,"question": 17,"tag": {"id": 1,"questionTags": [1,{"id": 2,"question": {"id": 19,"questionType": "LATEX","questionImagePath": null,"questionLatex": "多加一个标签","answerType": "LATEX","answerImagePath": null,"answerLatex": "现在是能搞到标签的id但是搞不到name","uploadTime": "2025-02-24 12:09:04","lastPracticeTime": null,"correctCount": 0,"incorrectCount": 0,"questionTags": [{"id": 3,"question": 19,"tag": {"id": 2,"questionTags": [3],"tag_name": "测试用例1"}},2]},"tag": 1}],"tag_name": "测试用例2"}}]},
这么深的嵌套就不说了,重复的内容还会再下次直接用数字代替,这不又得多建立一层映射关系,想想都麻烦。
最后感觉没啥办法了,想着保留级联操作,然后老老实实自己写SQL吧。手写的唯一好处就是可以定制化,虽然可能会有很多bug,不好维护,但是在功能都实现不了的情况下就不要求这么多了。
不过,自己动手造轮子是不可能的,是绝对不允许的。
这不,又找到了一个不错的好玩意,起码能解决我的问题。依旧是使用cascade来保证级联操作。然后使用EntityGraph来关联查询。但是不使用@JsonManagedReference和@JsonBackReference,因为这个其实适用于比较有明显的主次关系的结构。我的业务两者只能说使用频率有差距,但地位是相同的。所以其实这个不合适。
那不使用@JsonManagedReference和@JsonBackReference如何保证不无限循环的呢?
答案是@JsonView
有点小麻烦,需要在每个字段都标注(不知道能不能批量标注),但是正因为是具体到每个字段,而且可以标注多个,就可以非常灵活的选择展示哪些,不展示哪些,进而避免双向关联的循环。说白了就是把DTO换成了注解。靠人工手动标注来防止出错。
起码,这个方法是解决了我的问题。
最后补充几点,上述被我否定的几种方法,不是不好,只是不适用于我的业务罢了。其实EntityGraph挺好的,就是搭配JsonView,可以做到类似版本控制,就是可以写多个controller,给每个controller不同的JsonView就行,不需要修改原有的就可以灵活调整展示内容,有点类似增量开发。
再说一句,JsonView不同模式之间可以继承挺不错的。
相关文章:
后端之JPA(EntityGraph+JsonView)
不同表之间的级联操作或者说关联查询是很多业务场景都会用到的。 对于这种需求最朴素的方法自然是手动写关联表,然后对被关联的表也是手动插入数据。但是手写容易最后写成一堆shit代码,而且修改起来也是非常麻烦的。 学会使用现成的工具还是非常有利的…...
Java数据结构第十三期:走进二叉树的奇妙世界(二)
专栏:数据结构(Java版) 个人主页:手握风云 目录 一、二叉树的遍历 1.1. 前序遍历 1.2. 中序遍历 1.3. 后序遍历 1.4. 完整代码 二、二叉树的基本操作 2.1. 获取树中结点个数 2.1. 获取叶子结点个数 2.3. 获取第k层结点的个数 2.4. 获取二叉树的…...
JavaScript系列(86)--现代构建工具详解
JavaScript 现代构建工具详解 🔨 现代前端开发离不开构建工具,它们帮助我们处理模块打包、代码转换、资源优化等任务。让我们深入了解主流的构建工具及其应用。 构建工具概述 🌟 💡 小知识:构建工具主要解决代码转换…...
docker容器网络配置及常用操作
Linux内核实现名称空间的创建 ip netns(网络名称空间)命令 可以借助ip netns命令来完成对 Network Namespace 的各种操作。ip netns命令来自于iproute安装包,一般系统会默认安装,如果没有的话,请自行安装。 注意&am…...
Docker 性能优化指南
Docker 提供了强大的容器化功能,能够帮助开发者在不同的环境中构建、测试和部署应用。然而,随着容器化应用的不断增长,Docker 容器可能会面临一些性能瓶颈,影响其运行效率、资源占用和扩展能力。为了确保容器在生产环境中的高效运…...
课程1. 深度学习简介
课程1. 深度学习简介 神经网络结构逻辑回归XOR问题(异或问题) 中间特征的生成全连接神经网络中间网络层的激活函数Sigmoid函数Tanh函数ReLU函数其它激活函数 使用全连接神经网络解决 XOR 问题神经网络用于回归问题训练神经网络 不同类型的神经网络 附加材…...
【cuda学习日记】4.3 结构体数组与数组结构体
4.3 数组结构体(AoS)和结构体数组(SoA) AoS方法进行存储 struct innerStruct{float x;float y; };struct innerStruct myAOS[N];SoA方法来存储数据 struct innerArray{float x[N];float y[N]; };struct innerArray moa;如图说明…...
2025最新高维多目标优化:基于城市场景下无人机三维路径规划的导航变量的多目标粒子群优化算法(NMOPSO),MATLAB代码
一、基于导航变量的多目标粒子群优化算法(NMOPSO)介绍 基于导航变量的多目标粒子群优化算法(Navigation variable-based multi-objective particle swarm optimization,NMOPSO)是2025年提出的一种用于无人机路径规划的…...
数字IC后端设计实现OCC(On-chip Clock Controller)电路介绍及时钟树综合案例
数字IC后端时钟树综合专题(OCC电路案例分享) 复杂时钟设计时钟树综合(clock tree synthesis)常见20个典型案例 1、什么是OCC? 片上时钟控制器(On-chip Clock Controllers ,OCC),也称为扫描时钟控制器(Scan Clock Con…...
Linux内核,slub分配流程
我们根据上面的流程图,依次看下slub是如何分配的 首先从kmem_cache_cpu中分配,如果没有则从kmem_cache_cpu的partial链表分配,如果还没有则从kmem_cache_node中分配,如果kmem_cache_node中也没有,则需要向伙伴系统申请…...
本地部署DeepSeek-R1(Ollama+Docker+OpenWebUI知识库)
安装Ollama 打开 Ollama官网 https://ollama.com/下载安装 Ollama服务默认只允许本机访问,修改允许其它主机访问 OLLAMA_HOST0.0.0.0 ollama serve也可以添加系统环境变量 都知道模型体积很大,顺便也通过环境变量修改模型存放位置,我这…...
Java 实现快速排序算法:一条快速通道,分而治之
大家好,今天我们来聊聊快速排序(QuickSort)算法,这个经典的排序算法被广泛应用于各种需要高效排序的场景。作为一种分治法(Divide and Conquer)算法,快速排序的效率在平均情况下非常高ÿ…...
20250223下载并制作RTX2080Ti显卡的显存的测试工具mats
20250223下载并制作RTX2080Ti显卡的显存的测试工具mats 2025/2/23 23:23 缘起:我使用X99的主板,使用二手的RTX2080Ti显卡【显存22GB版本,准备学习AI的】 但是半年后发现看大码率的视频容易花屏,最初以为是WIN10经常更换显卡/来回更…...
element-ui的组件使用
1. 安装 Element UI(在文件夹最上面输入cmd进入dos窗口,然后输入安装指令 npm install element-ui --save) 2.在main.js文件全局引入(main.js文件负责 全局注册 ),在该文件注册的所有组件在其他文件都能直接调用,一般…...
医疗AI领域中GPU集群训练的关键技术与实践经验探究(上)
医疗AI领域中GPU集群训练的关键技术与实践经验探究(上) 一、引言 1.1 研究背景与意义 在科技飞速发展的当下,医疗 AI 作为人工智能技术与医疗领域深度融合的产物,正引领着医疗行业的深刻变革。近年来,医疗 AI 在疾病诊断、药物研发、健康管理等诸多方面取得了显著进展,…...
详解Redis淘汰策略
引言 Redis 是一个高性能的内存数据库,广泛应用于缓存系统、消息队列等场景。当 Redis 的内存达到限制时,需要根据一定的策略来淘汰数据,以便腾出空间给新数据。本文将深入解析 Redis 的内存淘汰机制,帮助更好地配置 Redis&#…...
HarmonyOS 5.0应用开发——鸿蒙接入高德地图实现POI搜索
【高心星出品】 文章目录 鸿蒙接入高德地图实现POI搜索运行结果:准备地图编写ArkUI布局来加载HTML地图 鸿蒙接入高德地图实现POI搜索 在当今数字化时代,地图应用已成为移动设备中不可或缺的一部分。随着鸿蒙系统的日益普及,如何在鸿蒙应用中…...
nginx关于配置SSL后启动失败原因分析
在配置SSL后,启动./nginx失败,报错提示如下: nginx: [emerg] the "ssl" parameter requires ngx_http_ssl_module in /usr/local/nginx-1.27.4/conf/nginx.conf:36 这个错误提示表在配置nginx启用SSL时,nginx未启用 ng…...
【自学嵌入式(9)ESP8266网络服务器的使用】
ESP8266网络服务器的使用 ESP8266WiFi 库① WiFiClass② WiFiClient③ WiFiServer④ WiFiUDP ESP8266WiFiMulti 库① WiFiMulti ESP8266WebServer 库① ESP8266WebServer 网络服务器实例在浏览器中控制ESP8266指示灯将开发板引脚状态显示在网页中 在之前的文章中,曾…...
危化品经营单位安全管理人员的职责及注意事项
危化品经营单位安全管理人员肩负着保障经营活动安全的重要责任,以下是其主要职责及注意事项: 职责 1. 安全制度建设与执行:负责组织制定本单位安全生产规章制度、操作规程和生产安全事故应急救援预案,确保这些制度符合国家相关法…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
