【问题标题】:JPA: java.lang.StackOverflowError on adding toString method in entity classesJPA:在实体类中添加 toString 方法时出现 java.lang.StackOverflowError
【发布时间】:2014-07-21 07:41:18
【问题描述】:

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

}

【问题讨论】:

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


    【解决方案1】:

    根据添加的 Student 类更新

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

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

    这意味着调用Teacher.toString()Student.toString() 最终将导致一个永无止境的循环,其中:Teacher.toString() 隐式调用Student.toString(),而后者又隐式调用Teacher.toString(),而后者又调用@987654335 @,然后调用...

    2 个.toString() 实现在一个永无止境的循环中不断地来回调用,来回调用,最终溢出堆栈并导致java.lang.StackOverflowError

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

    【讨论】:

    • 通过在底部添加Student实体的代码来编辑帖子。
    • 刚刚将Guide实体中的toString方法更新为这个public String toString() { return "Guide [id=" + id + ", staffId=" + staffId + ", name=" + name + ", salary=" + salary + ", students.size()=" + students.size() + "]"; }。它解决了这个问题。谢谢。
    • @skip - 我已根据您添加的 Student 课程更新了我的答案。我最初的猜测是正确的,我的回答应该可以帮助您纠正问题。
    【解决方案2】:

    您必须从 toString() 方法中排除多余的参数。

    GL

    【讨论】:

      【解决方案3】:

      实体班老师有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
                  + "]";
      }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2019-04-22
        • 2012-10-24
        • 2012-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-08
        • 1970-01-01
        • 2012-05-08
        相关资源
        最近更新 更多