一切正常,直到我添加toSting()了实体类。
toSting()
之后,我开始在运行时收到以下错误:
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.toString(),因此发生了什么:
Student.toString()
在中Teacher.toString(),您Student.toString()通过将students成员放在String串联语句中隐式调用+ students +。Student.toString()通过teacher在String串联语句中包含成员,代码内的功能类似。
Teacher.toString()
students
String
+ students +
teacher
这意味着调用Teacher.toString()或Student.toString()将最终导致永无止境的循环,其中:Teacher.toString()隐式调用Student.toString(),后者又隐式调用Teacher.toString(),后者又调用Student.toString(),后者又调用…
这2个.toString()实现以不断循环的方式来回调用,来回调用,来回调用,这最终使堆栈溢出并导致java.lang.StackOverflowError。
.toString()
java.lang.StackOverflowError
若要更正此问题,应删除.toString()对实体方法的隐式引用。作为替代,你可以有Teacher.toString()简单输出length()的的students收集和可能包括的名单Student姓名(或名称)。并在中Student.toString(),仅包括Teacher.name成员。
length()
Student
Teacher.name