JPA:关于在实体类中添加toString方法的java.lang.StackOverflowError [英] JPA: java.lang.StackOverflowError on adding toString method in entity classes
问题描述
一切正常,直到我在实体类中添加了toSting()
.
Everything worked fine until I added toSting()
in my entity classes.
此后,我在运行时开始出现以下错误:
After which I start getting the following error in runtime:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at java.lang.StringBuilder.<init>(Unknown Source)
at entity.Guide.toString(Guide.java:51)
at java.lang.String.valueOf(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at entity.Student.toString(Student.java:45)
...
@Entity
public class Teacher {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
@OneToMany(mappedBy="teacher", cascade={CascadeType.PERSIST})
private Set<Student> students = new HashSet<Student>();
public Teacher() {}
public Teacher(String name) {
this.name = name;
}
public Set<Student> getStudents() {
return students;
}
public void addStudent(Student student) {
students.add(student);
student.setTeacher(this);
}
@Override
public String toString() {
return "Teacher[id=" + id + ", name=" + name
+ ", students=" + students + "]";
}
}
public class SnafuClient {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("snafu");
EntityManager em = emf.createEntityManager();
EntityTransaction txn = em.getTransaction();
try {
txn.begin();
Query query = em.createQuery("select teacher from Teacher teacher");
List<Teacher> teachers = query.getResultList();
for (Teacher teacher: teachers) {
System.out.println(teacher);
}
txn.commit();
} catch(Exception e) {
if(txn != null) { txn.rollback(); }
e.printStackTrace();
} finally {
if(em != null) { em.close(); }
}
}
}
添加了用于学生实体的代码
@Entity
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
@ManyToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
@JoinColumn(name="teacher_id")
private Teacher teacher;
public Student() {}
public Student(String name, Teacher teacher) {
this.name = name;
this.teacher = teacher;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student [id=" + id +
+ ", name=" + name + ", teacher=" + teacher + "]";
}
}
推荐答案
根据添加的Student类进行了更新
根据堆栈跟踪,您的问题与Student.toString()
相关,所以发生了以下情况:
Updated based on the addition of the Student class
According to the stack trace, your problem is associated with the Student.toString()
, so here's what is happening:
在Teacher.toString()
中,您通过将students
成员放在String
串联语句:+ students +
中隐式调用Student.toString()
.在Student.toString()
中,代码通过在String
串联语句中包含teacher
成员来执行类似的操作.
In Teacher.toString()
, you are implicitly calling the Student.toString()
by placing the students
member within a String
concatenation statement: + students +
. Within Student.toString()
the code does something similar, by including the teacher
member within a String
concatenation statement.
这意味着调用Teacher.toString()
或Student.toString()
将最终导致永无止境的循环,其中:Teacher.toString()
隐式调用Student.toString()
,后者又隐式调用Teacher.toString()
,后者又调用
This means that calling either Teacher.toString()
or Student.toString()
will end up causing a never-ending loop where: Teacher.toString()
implicitly calls Student.toString()
, which in turn implicitly calls Teacher.toString()
, which in turn calls Student.toString()
, which in turn calls...
这两个.toString()
实现始终以永无止境的循环来回调用,最终导致堆栈溢出并产生java.lang.StackOverflowError
.
The 2 .toString()
implementations keep calling back and forth, back and forth, back and forth, in a never-ending loop, which eventually overflows the stack and results in a java.lang.StackOverflowError
.
要解决此问题,应删除对实体的.toString()
方法的隐式引用.作为替代,您可以让Teacher.toString()
简单地输出students
集合的length()
,并且可能包括Student
名称的列表.在Student.toString()
中,只需包含Teacher.name
成员.
To correct the problem, you should remove the implicit references to the .toString()
methods of the entities. As a replacement, you could have Teacher.toString()
simply output the length()
of the students
collection and maybe include a list of the Student
name(s). And in the Student.toString()
, simply include the Teacher.name
member.
这篇关于JPA:关于在实体类中添加toString方法的java.lang.StackOverflowError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!