JPA:java.lang.StackOverflowError在实体类中添加toString方法

时间:2014-05-31 17:45:36

标签: hibernate stack-overflow jpql tostring jpa-2.1

在我的实体类中添加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 + "]";
    }   

}

3 个答案:

答案 0 :(得分:15)

根据添加的学生班级

进行了更新

根据堆栈跟踪,您的问题与Student.toString()相关联,所以在这里发生了什么:

Teacher.toString()中,您通过将Student.toString()成员置于students连接语句String中隐式调用+ students +。在Student.toString()内,代码执行类似操作,方法是将teacher成员包含在String连接语句中。

这意味着调用Teacher.toString()Student.toString()将导致永无止境的循环,其中:Teacher.toString()隐式调用Student.toString(),后者隐式调用Teacher.toString() 1}},然后调用Student.toString(),后者又调用...

2个.toString()实现在一个永无止境的循环中来回,来回,来回,最终溢出堆栈并产生java.lang.StackOverflowError

要解决此问题,您应该删除对实体的.toString()方法的隐式引用。作为替代,您可以Teacher.toString()只输出length()集合的students,并且可以包含Student名称的列表。在Student.toString()中,只需添加Teacher.name成员。

答案 1 :(得分:0)

实体班级教师遇到toString()问题:

@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
            + "]";
}

}

答案 2 :(得分:0)

必须从toString()方法中排除冗余参数。

  • 在Java中,将Lombok@ToString.Exclude一起使用
  • 在Kotlin中,将custom annotation@ExcludeToString一起使用

GL