使用Jpa自带的级联注解造成死循环问题

前言

使用Jpa持久化框架级联注解@OneToOne或者@OneToMany等。双向关联查询时,会造成数据死循环

例子

实体类定义

1、定义一个部门实体类

less 复制代码
@Data
@Entity
@Table(name = "t_department")
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToMany(mappedBy = "department", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Employee> employees;

}

2、定义一个销售实体类

less 复制代码
@Data
@Entity
@Table(name = "t_employee")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;


    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;

}

双向关联 3、dao层定义

kotlin 复制代码
@Repository
public interface DepartmentRepository extends JpaRepository<Department, Long>,
        JpaSpecificationExecutor<Department> {


}

4、

kotlin 复制代码
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long>,
        JpaSpecificationExecutor<Employee> {


}

5、接口定义

typescript 复制代码
@RestController
public class IndexController {

    @Autowired
    private DepartmentRepository departmentRepository;

    @GetMapping("/index")
    public String index() {;
        Department department = new Department();
        department.setName("bbb");
        Employee employee = new Employee();
        employee.setName("aaa");
        employee.setDepartment(department);
        department.setEmployees(List.of(employee));
        departmentRepository.save(department);
        return "success";
    }


    @GetMapping("/findById")
    public Department findById(@RequestParam Long id) {
        return departmentRepository.findById(id).orElse(null);
    }
}

6、调用

bash 复制代码
http://ip:端口/index

保存数据

7、 这个时候,调用

bash 复制代码
http://ip:端口/findById?id=2

会发现数据出现死循环

这个并不是bug,这个在toString()方法中,一层一层嵌套导致的,只需要中断其嵌套就行

解决方法

1、 使用@JsonIgnoreProperties中断其死循环

less 复制代码
@Data
@Entity
@Table(name = "t_department")
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @JsonIgnoreProperties({"department"})
    @OneToMany(mappedBy = "department", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Employee> employees;

}

在实体类两边都加上,再次访问,数据为

2、 使用实体类dto

定义一个实体类

kotlin 复制代码
@Data
public class DepartmentDto {

    private Long id;

    private String name;

}
less 复制代码
@GetMapping("/findById1")
public DepartmentDto findById1(@RequestParam Long id) {
    Department department = departmentRepository.findById(id).orElse(null);
    DepartmentDto departmentDto = new DepartmentDto();
    BeanUtils.copyProperties(department, departmentDto);
    return departmentDto;
}

3、 使用 @JsonIgnore注解

less 复制代码
@Data
@Entity
@Table(name = "t_department")
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @JsonIgnore
    @OneToMany(mappedBy = "department", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Employee> employees;

}

总结

使用Jpa自带的级联注解造成死循环问题,解决方法很多种,,开发过程中,根据自己需要解决

相关推荐
shuoshuohaohao2 小时前
MyBatis 小知识点
java·spring·mybatis
海上小飞龙3 小时前
【KMP算法-下篇】同一道题:Java 库函数 2600 微秒,手写 KMP 16 微秒
java·开发语言·算法
谢亮_vipxieliang4 小时前
泛型擦除、通配符与 PECS 一次讲透
java·面试
八解毒剂4 小时前
【计组】中央处理器CPU
java·开发语言·计算机组成原理
打工仔折腾 AI5 小时前
工业场景下时序库与实时计算一体化架构选型实践对比
java·开发语言·后端·python·性能优化·架构·ai agent 实战
ZealSinger5 小时前
Java虚拟线程上线后瓶颈转移到哪看三层
java·开发语言·firefox
2601_961133285 小时前
盘立方软件指标文华期货公式下载
java
蜗牛互联网5 小时前
长任务多Agent共享文件系统的Manifest交接模式
java·人工智能·后端
Sirens.5 小时前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法
sunshine22 girl6 小时前
Java学习五 面向对象高级5 内部类1
java·学习