如何解决循环引用的问题

news2024/10/7 4:22:35
本文已收录于专栏
《Java》

目录

  • 概念说明
  • 发现问题
  • 解决问题
    • 分析问题
    • 具体解决
      • 注解说明
      • 代码实现
      • 效果展示
  • 总结提升

概念说明

  循环引用是指在对象之间存在相互引用的情况。具体来说,当一个对象A引用了另一个对象B,而对象B又引用了对象A,它们之间形成了一个循环引用关系。
  循环引用可能会导致一些问题,特别是在序列化和反序列化过程中。在序列化过程中,如果不进行特殊处理,循环引用会导致无限递归的序列化,最终导致栈溢出异常。在反序列化过程中,循环引用可能会导致对象的重复创建,破坏对象的一致性。

发现问题

  当我们实现了类之间的多对多关系的时候,当我们从数据库中查询相关数据的时候,会发现查询出来的结果会存在对象之间嵌套的问题,最后导致堆栈溢出的问题。
Classes类

@Service
@Entity
@Table(name="Classes")
public class Classes implements ApplicationRunner {

    private Long id;

    private Long classId;

    private String className;

    private Integer isDelete;


    @OneToMany(mappedBy = "classes")

    private List<ClassesActor> actorClasses;

	//getter和setter方法
	
	}

Actor类

@Service
@Entity
@Table(name = "Actor")
public class Actor  {
    private Long id;

    private String code;

    private String name;

    private String phone;

	@OneToMany(mappedBy = "actor")
    private List<ClassesActor> actorClasses;
	
	//getter和setter方法
	}

ClassesActor类

@Entity
public class ClassesActor {

    private Long id;

    @ManyToOne
    @JoinColumn(name = "actor_id")
    private Actor actor;

    @ManyToOne
    @JoinColumn(name = "class_id")
    private Classes classes;

	//getter和setter方法
	}

  当我在实际的业务中去查询classes相关信息的时候会发现,Classes对象中有ClassesActor对象,点开ClassesActor对象中海油Classes对象而且这些对象都是同一个对象。所以就出现了循环嵌套的问题。
在这里插入图片描述

解决问题

分析问题

   1. 我们要清楚对于对象的属性进行操作属于数据序列化的过程。数据序列化是将对象转换为字节流或其他形式的数据,以便在网络传输、存储或跨平台传递时使用。在数据序列化过程中,对象的属性值会被转换为字节流或其他格式的数据,并随后可以被反序列化为对象。
  2.通过对问题的分析我们可以通过序列化操作来解决序列化多个相同对象的问题,这样我们就把问题缩小到序列化中。
  3.明确如何在序列化的过程中去控制相同的对象只序列化一次,我们的问题也就迎刃而解了。

具体解决

  通过@JsonManagedReference和@JsonBackReference注解帮助我们解决相同的对象只序列化一次的问题。

注解说明

  • 「@JsonManagedReference 」注解用于标注在实体类的属性上,表示该属性是一个“被管理的引用”。它的作用是告诉Jackson在序列化过程中,该属性是“正向”引用,需要被序列化输出。同时,它还需要配合@JsonBackReference注解一起使用,指定“反向”引用的属性。
  • 「@JsonBackReference 」 注解用于标注在实体类的属性上,表示该属性是一个“反向引用”。它的作用是告诉Jackson在序列化过程中,该属性是“反向”引用,不需要被序列化输出。相反,它会通过@JsonManagedReference注解指定的属性来进行序列化输出。

代码实现

Classes类

@Service
@Entity
@Table(name="Classes")
public class Classes implements ApplicationRunner {

    private Long id;

    private Long classId;

    private String className;

    private Integer isDelete;


    @OneToMany(mappedBy = "classes")
	@JsonManagedReference(value = "class-actorClasses")
    private List<ClassesActor> actorClasses;

	//getter和setter方法
	
	}

Actor类

@Service
@Entity
@Table(name = "Actor")
public class Actor  {
    private Long id;

    private String code;

    private String name;

    private String phone;

	@OneToMany(mappedBy = "actor")
	@JsonManagedReference(value = "actor-classes")
    private List<ClassesActor> actorClasses;
	
	//getter和setter方法
	}

ClassesActor类

@Entity
public class ClassesActor {

    private Long id;

    @ManyToOne
    @JoinColumn(name = "actor_id")
    @JsonBackReference(value = "actor-classes")
    private Actor actor;

    @ManyToOne
    @JoinColumn(name = "class_id")
    @JsonBackReference(value = "class-actorClasses")
    private Classes classes;

	//getter和setter方法
	}

  通过使用@JsonManagedReference和@JsonBackReference注解,Jackson库能够正确处理实体类之间的循环引用关系,避免了无限递归的序列化问题。当一个类中出现了多个@JsonBackReference注解要有value值进行区分和加以对应。

效果展示

在这里插入图片描述

总结提升

  这两个注解只适用于序列化过程,对于反序列化过程是不起作用的。如果需要在反序列化时处理循环引用问题,可以考虑使用@JsonIdentityInfo注解或自定义序列化和反序列化逻辑来处理。



在这里插入图片描述


🎯 此文章对你有用的话记得留言+点赞+收藏哦🎯

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

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

相关文章

软件研发开发人员成本计算器

写了个简单的人员工资计算器&#xff0c;用最简单的人天数计算研发投入&#xff0c;其他费用计算稍后补充完善 软件研发成本计算 ——高级工程师中级工程师初级工程师平均日工资项目阶段高级工程师人天中级工程师人天初级工程师人天调研方案产品设计软件开发测试部署培训试运…

操作系统(王道)- 初识操作系统

一、什么是操作系统&#xff1f; 操作系统可以这么理解 操作系统的定义&#xff1a; 操作系统是整个计算机的硬件和软件的管理者&#xff01;&#xff01;&#xff01; 二、操作系统的功能和目标 作为计算机硬件和软件的管理者&#xff0c;操作系统做了什么&#xff1f; 操作系…

安达发|工业系统APS软件与MES软件有哪些区别?

MES 和 APS 有什么区别&#xff1f;MES 是一个制造执行系统&#xff0c;APS 是一个高级计划排程系统系统&#xff0c;两者是互补的关系&#xff0c;APS 和 MES 可以实现计划和车间执行的闭环管理模式。MES 和 APS 有什么区别&#xff1f; mes和aps的区别: MES 是智能化工厂…

【1++的Linux】之进程(一)

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的Linux】 文章目录 一&#xff0c;冯诺依曼与操作系统概念1.1 冯诺依曼体系结构1.2 操作系统 二&#xff0c;进程的基本概念 一&#xff0c;冯诺依曼与操作系统概念 1.1 冯诺依曼体系结构 如…

如何关闭网页版【知乎】等页面的登录弹窗(以谷歌浏览器为例)

如何关闭网页版【知乎】等页面的登录弹窗&#xff08;以谷歌浏览器为例&#xff09; 在不登陆知乎的情况下仍然可以正常浏览页面&#xff0c;可是每次打开新页面会重复出现弹窗要求用户登录。如何屏蔽掉这一弹窗呢? 在浏览器中把知乎网址设置为禁止使用javascript 在chrome的…

C#盯盘小工具,“监”

也是一个小工具&#xff0c;用来看大A股票和主要指数行情的。 如果你是一个上班族&#xff0c;同时你也是一颗小韭菜&#xff0c;a股在开市交易盘中时刻惦记着股票是涨了还是跌了&#xff0c;却不能时刻盯着手机看行情&#xff0c;也不能在电脑上开着同花顺来回切窗口&#xff…

4.CSS(一)

目录 一、CSS简介 二、CSS基础选择器 &#xff08;一&#xff09;标签选择器 &#xff08;二&#xff09;类选择器 类选择器-多类名 &#xff08;三&#xff09;id选择器 &#xff08;四&#xff09;通配符选择器 &#xff08;五&#xff09;总结 三、CSS字体属性 &…

Acwing.906 区间分组(贪心)

题目 给定N个闭区间[ai,bi]&#xff0c;请你将这些区间分成若千组&#xff0c;使得每组内部的区间两两之间(包括端点)没有交集&#xff0c;并使得组数尽可能小。 输出最小组数。 输入格式 第一行包含整数N&#xff0c;表示区间数。 接下来N行&#xff0c;每行包含两个整数ai…

【算法基础】2.2 字典树/前缀树 Trie

文章目录 知识点cpp结构体模板 模板例题835. Trie字符串统计❤️❤️❤️❤️❤️143. 最大异或对&#x1f62d;&#x1f62d;&#x1f62d;&#x1f62d;&#x1f62d;&#xff08;Trie树的应用&#xff09; 相关题目练习208. 实现 Trie (前缀树)1804. 实现 Trie &#xff08;…

轮转数组——左旋数组,右旋数组

题目链接&#xff1a;力扣 左旋转字符串&#xff1a;【1234567】—左旋3下—>【4567123】 反转区间为前n的子串【3214567】反转区间为n到末尾的子串【3217654】反转整个字符串【4567123】 右旋转字符串&#xff1a;【1234567】—右旋3下—>【5671234】 反转整个字符…

一图看懂 pandas 模块(1):提供高性能、易用的数据结构和数据分析工具,资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 pandas 模块&#xff1a;提供高性能、易用的数据结构和数据分析工具&#xff0c;资料整理笔记&#xff08;大全&#xff09; &#x1f9ca;摘要&#x1f9ca;模块图&#x…

SAP-MM-物料版次

业务背景介绍 UF公司其产成品会根据客户需求进行细节上零件变更,每次都需新增物料主数据以及搭建新的BOM和对应的工艺路线进行数据处理(即对客户A0001的产成品从A0010到B0010的变化,但物料描述还是原来的描述) 新增物料编号进行库存管控是较为合理的需求,但是因UF销售业务员…

在LLM的支持下使游戏NPC具有记忆化的方法

问题 使用GPT这样的LLM去处理游戏中的NPC和玩家的对话是个很好的点子&#xff0c;那么如何处理记忆化的问题呢。 因为LLM的输入tokens是有限制的&#xff0c;所以伴随着问题的记忆context是有窗口大小限制的&#xff0c;将所有的记忆输入LLM并不现实。 所以这里看到了stanfo…

Damiler EDI 项目 Excel 方案开源介绍

准备下载和运行 Daimler EDI 到 Excel 使用 Excel 生成一系列 EDI 文档与 Daimler 通信。 下载工作流 下载示例文件 Daimler EDI & Excel 方案简介 本文将继续分享Daimler示例工作流&#xff1a;使用Excel端口和Email端口生成一系列文件&#xff0c;完成与Daimler的…

解锁编程世界的魔法密码:探索算法的奥秘与应用

一个程序员一生中可能会邂逅各种各样的算法&#xff0c;但总有那么几种&#xff0c;是作为一个程序员一定会遇见且大概率需要掌握的算法。今天就来聊聊这些十分重要的“必抓&#xff01;”算法吧~* 一&#xff1a;引言 算法是解决问题和优化程序性能的核心&#xff0c;它是一…

Redis实战案例20-优化秒杀(一人一单)

查询优惠券判断秒杀库存&#xff1b;查询订单&#xff1b;校验一人一单&#xff1b;减库存、创建订单&#xff1b; 以上均为串行操作&#xff0c;执行效率不高&#xff0c;在高并发的场景下性能很一般 问题引出&#xff1a;如何在Redis中完成秒杀判断和校验一人一单的问题&…

【LeetCode热题100】打卡第39天:数组中第K个最大元素最大正方形

文章目录 【LeetCode热题100】打卡第39天&#xff1a;数组中第K个最大元素&最大正方形⛅前言 数组中的第K个最大元素&#x1f512;题目&#x1f511;题解 最大正方形&#x1f512;题目&#x1f511;题解 【LeetCode热题100】打卡第39天&#xff1a;数组中第K个最大元素&…

若依(Ruoyi)前后端分离版项目部署到服务器(Linux环境)后,刷新页面报错:404 Not Found

原文章:若依(ruoyi)前后端分离版使用教程之若依后端部署阿里云服务器步骤(超详细)_蓝多多的小仓库的博客-CSDN博客 问题: 在若依项目部署服务器后,可以正常运行,但如果执行刷新页面操作,便会出现404 Not Found。 原因: Nginx未正确配置。由于后台路由采用History模式…

软件测试银行项目面试过程

今天参加了一场比较正式的面试&#xff0c;汇丰银行的视频面试。在这里把面试的流程记录一下&#xff0c;结果还不确定&#xff0c;但是面试也是自我学习和成长的过程&#xff0c;所以记录下来大家也可以互相探讨一下。 请你做一下自我介绍&#xff1f;&#xff08;汇丰要求英…

【JAVA】为char所提供包装类——Character类

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️初识JAVA】 文章目录 前言Character 类装箱(boxing)拆箱(unboxing)转义序列Java的转义序列实例Character 方法isDigit()isLetter()isWhitespace()toUpperCase()toLowerCase()compareTo()isAlphabetic…