使用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自带的级联注解造成死循环问题,解决方法很多种,,开发过程中,根据自己需要解决

相关推荐
D_aniel_5 分钟前
排序算法-计数排序
java·排序算法·计数排序
极小狐11 分钟前
极狐GitLab 通用软件包存储库功能介绍
java·数据库·c#·gitlab·maven
旧故新长23 分钟前
Browserless 快速上手
java
java1234_小锋29 分钟前
Spring Bean有哪几种配置方式?
java·后端·spring
?abc!30 分钟前
缓存(5):常见 缓存数据淘汰算法/缓存清空策略
java·算法·缓存
DanB2443 分钟前
Java笔记4
java·开发语言·笔记
Dddle11 小时前
C++:this指针
java·c语言·开发语言·c++
阿乾之铭1 小时前
Spring Boot 参数验证
java·数据库·mysql
佩奇的技术笔记1 小时前
Java学习手册:微服务设计原则
java·微服务
jiunian_cn1 小时前
【c++】异常详解
java·开发语言·数据结构·c++·算法·visual studio