JPA:关于在实体类中添加toString方法的java.lang.StackOverflowError [英] JPA: java.lang.StackOverflowError on adding toString method in entity classes

查看:208
本文介绍了JPA:关于在实体类中添加toString方法的java.lang.StackOverflowError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一切正常,直到我在实体类中添加了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆