企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] # 1. 数据死循环 当两个实体类相互引用时,这时数据传递到前端会形成死循环问题。 ```java public class Student implements Serializable { //Student中引用Score @OneToMany(mappedBy = "student") private List<Score> scoreList; } public class Score implements Serializable { //Score中引用Student @ManyToOne(targetEntity = Student.class) @JoinColumn(name = "student_id", referencedColumnName = "id") private Student student; } ``` :-: ![](https://img.kancloud.cn/03/84/0384ed022ecbf8cdc4c495051434b17b_2502x388.png) 死循环结果 后端报如下异常: ```java java.lang.IllegalStateException: Cannot call sendError() after the response has been committed at org.apache.catalina.connector.ResponseFacade.checkCommitted(ResponseFacade.java:504) ~[tomcat-embed-core-10.1.8.jar:10.1.8] ``` <br/> <mark>解决办法:标记注解 @JsonIgnoreProperties 来忽略属性。</mark> ```java public class Student implements Serializable { //忽视Score中的student变量 @JsonIgnoreProperties("student") @OneToMany(mappedBy = "student") private List<Score> scoreList; } public class Score implements Serializable { //忽视Student里面的scoreList变量 @JsonIgnoreProperties("scoreList") @ManyToOne(targetEntity = Student.class) @JoinColumn(name = "student_id", referencedColumnName = "id") private Student student; } ``` <br/> # 2. lombok导致的死循环 lombok 框架中提供的注解`@Data`、`@ToString`、`@EqualsAndHashCode`会用到当前类的所有变量来重写对应的方法,在调用这些方法时就会进入死循环。 ```java public class Student implements Serializable { @OneToMany(mappedBy = "student") private List<Score> scoreList; //Student的toString方法用到了this.getScoreList() public String toString() { Integer var10000 = this.getId(); return "Student(id=" + var10000 + ", name=" + this.getName() + ", age=" + this.getAge() + ", scoreList=" + this.getScoreList() + ")"; } } public class Score implements Serializable { @ManyToOne(targetEntity = Student.class) @JoinColumn(name = "student_id",referencedColumnName = "id") private Student student; //Score的toString方法用到了this.getStudent() public String toString() { Integer var10000 = this.getId(); return "Score(id=" + var10000 + ", name=" + this.getName() + ", score=" + this.getScore() + ", student=" + this.getStudent() + ")"; } } ``` 两个类的 toString() 方法,都进行了相互引用,这时如果调用 toString() 就会进入死循环并抛出如下异常。 ```java java.lang.StackOverflowError: null at java.base/jdk.internal.math.FloatingDecimal.getBinaryToASCIIConverter(FloatingDecimal.java:1750) ~[na:na] at java.base/jdk.internal.math.FloatingDecimal.getBinaryToASCIIConverter(FloatingDecimal.java:1738) ~[na:na] at java.base/jdk.internal.math.FloatingDecimal.toJavaFormatString(FloatingDecimal.java:70) ~[na:na] at java.base/java.lang.Double.toString(Double.java:312) ~[na:na] at java.base/java.lang.Double.toString(Double.java:769) ~[na:na] at java.base/java.lang.StringConcatHelper.stringOf(StringConcatHelper.java:453) ~[na:na] at learn.bootjpa.entity.Score.toString(Score.java:9) ~[classes/:na] ``` <br/> <mark>解决办法1:不调用toString、equals、hashCode方法。</mark> <mark>解决办法2:重写 toString、equals、hashCode方法,避免相互引用。</mark> ```java public class Student implements Serializable { @JsonIgnoreProperties("student") @OneToMany(mappedBy = "student") private List<Score> scoreList; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return id.equals(student.id); } @Override public int hashCode() { return Objects.hash(id); } @Override public String toString() { List<Score> scoreList2 = new ArrayList<>(); for (Score score : this.getScoreList()) { Score score2 = new Score(); BeanUtils.copyProperties(score, score2); score2.setStudent(null); scoreList2.add(score2); } return "Student(id=" + id + ", name=" + name + ", age=" + age + ", scoreList=" + scoreList2 + ")"; } } ```