ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
在使用注解`@OneToOne`、`@OneToMany`/`@ManyToOne`、`@ManyToMany`进行双向多表查询时需要注意下面两个问题。 [TOC] # 1. 死循环问题 ![](https://img.kancloud.cn/c5/a1/c5a1170fa01181c2265daa57d47ceefd_1533x472.jpg) lombok 框架中提供的注解`@Data`、`@ToString`、`@EqualsAndHashCode`,会用到当前类的所有变量来重写对应的方法,在调用这些方法时就可能进入死循环,比如`toString`方法。 <br/> 在`Trainee`中调用`Teacher`,`Teacher`又调用了`Trainee`就会形成一个死循环,这样在进行查询时就会抛出如下异常,导致查询失败。 ```java java.lang.StackOverflowError at java.base/java.lang.StringUTF16.checkBoundsOffCount(StringUTF16.java:1482) ``` 解决办法如下: **1. 不调用`toString`、`equals`、`hashCode`方法** **2. 重写`toString`、`equals`、`hashCode`方法** 自己重写`toString`、`equals`、`hashCode`方法,让这些方法不要调用全部的变量。 ```java public class Trainee { @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Trainee trainee = (Trainee) o; return id.equals(trainee.id) && name.equals(trainee.name) && age.equals(trainee.age) && gender.equals(trainee.gender) && //1. 不要直接调用整个 teacher teacher.equals(trainee.teacher.getId()); } @Override public int hashCode() { //这样直接调用teacher来重写hashCode方法,当调用到hashCode方法时就会死循环了 //return Objects.hash(id, name, age, gender, teacher); //要么不使用 teacher 来重写hashCode方法,要么不要直接使用 teacher //return Objects.hash(id, name, age, gender); return Objects.hash(id, name, age, gender, teacher.getId()); } @Override public String toString() { return "Trainee{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", age=" + age + ", gender='" + gender + '\'' + //直接调用整个 teacher重写 toString方法,当调用到该方法时就会死循环了 //", teacher=" + teacher + //要么不使用 teacher 来重写toString方法,要么不要直接使用 teacher ", teacher=" + teacher.getId() + '}'; } } ``` <br/> # 2. 后端数据传递到前端 如下两个实体类互相引用,则数据传递到前端时也会造成死循环。 ```java public class Trainee { //Trainee中引用Teacher private Teacher teacher; } public class Teacher { //Teacher中引用Trainee private List<Trainee> traineeList; } ``` 传递到前端得到如下类似数据,是无限的。 ![](https://img.kancloud.cn/3d/da/3ddaf0f57196a625fec718aeba8605fa_1528x247.jpg) 后端将会抛出如下异常: ``` java.lang.IllegalStateException: Cannot call sendError() after the response has been committed ``` <br/> 解决办法如下: **1. 添加注解`@JsonIgnoreProperties`来忽略属性** (1)引入如下依赖。 ```xml <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.12.5</version> </dependency> ``` (2)标注注解`@JsonIgnoreProperties`,忽略属性。 ```java public class Trainee { //忽略 Teacher.traineeList 属性 @JsonIgnoreProperties(value = {"traineeList"}) private Teacher teacher; } public class Teacher { //忽略 Trainee.teacher 属性 @JsonIgnoreProperties(value = {"teacher"}) private List<Trainee> traineeList; } ```