java - 在 OneToMany 和 ManyToMany 映射中获取 StackOverflow

标签 java hibernate java-8 jpa-2.0 postgresql-9.6

当我尝试执行以下代码时,出现 StackOverflow 异常

@Test
public void testMappings() {
    EntityManager em = factory.createEntityManager();
    Query q = em.createQuery("select f from Student f");
    System.out.println(q.getResultList());
    em.close();
}

我有三个实体(学生类(class)类(class)注册),如下所示

enter image description here

异常(exception)情况如下

java.lang.StackOverflowError
    at org.jboss.logging.Log4jLogger.doLog(Log4jLogger.java:40)
    at org.jboss.logging.Logger.debug(Logger.java:385)
    at org.hibernate.engine.jdbc.spi.SqlStatementLogger.logStatement(SqlStatementLogger.java:109)
    at org.hibernate.engine.jdbc.spi.SqlStatementLogger.logStatement(SqlStatementLogger.java:94)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:181)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:160)
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.prepareQueryStatement(AbstractLoadPlanBasedLoader.java:257)
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeQueryStatement(AbstractLoadPlanBasedLoader.java:201)
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:137)
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102)
    at org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:100)
    at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:693)
    at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:92)
    at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1933)
    at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:558)

谁能告诉我哪里出了问题

完整源代码可在 https://github.com/alexman31/jpatest/ 中找到

更新 1

根据@Anthony@Nonika的建议,我删除了所有lombok注释并生成显式setter/getters、toString、equals和hashcode。但我仍然遇到同样的异常。

Student.java

@Entity
@Table(name = "student")
public class Student {

    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToMany
    @JoinTable(name = "course_registration", joinColumns = @JoinColumn(name = "student_id"), inverseJoinColumns = @JoinColumn(name = "course_id"))
    private Set<Course> likedCourses;


    @OneToMany(mappedBy = "student")
    private Set<CourseRegistration> registrations;


    // additional properties

    public Student() {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Student)) return false;

        Student student = (Student) o;

        if (getId() != null ? !getId().equals(student.getId()) : student.getId() != null) return false;
        if (getName() != null ? !getName().equals(student.getName()) : student.getName() != null) return false;
        if (getLikedCourses() != null ? !getLikedCourses().equals(student.getLikedCourses()) : student.getLikedCourses() != null)
            return false;
        return getRegistrations() != null ? getRegistrations().equals(student.getRegistrations()) : student.getRegistrations() == null;

    }

    @Override
    public int hashCode() {
        int result = getId() != null ? getId().hashCode() : 0;
        result = 31 * result + (getName() != null ? getName().hashCode() : 0);
        result = 31 * result + (getLikedCourses() != null ? getLikedCourses().hashCode() : 0);
        result = 31 * result + (getRegistrations() != null ? getRegistrations().hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", likedCourses=" + likedCourses +
                ", registrations=" + registrations +
                '}';
    }

    public Long getId() {
        return id;
    }

    public Set<Course> getLikedCourses() {
        return likedCourses;
    }


    public Set<CourseRegistration> getRegistrations() {
        return registrations;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setLikedCourses(Set<Course> likedCourses) {
        this.likedCourses = likedCourses;
    }

    public void setRegistrations(Set<CourseRegistration> registrations) {
        this.registrations = registrations;
    }
}

类(class).java

@Entity
@Table(name = "course")
public class Course {

    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToMany(mappedBy = "likedCourses")
    private Set<Student> likes;

    @OneToMany(mappedBy = "course")
    private Set<CourseRegistration> registrations;
    // additional properties

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Course)) return false;

        Course course = (Course) o;

        if (getId() != null ? !getId().equals(course.getId()) : course.getId() != null) return false;
        if (getName() != null ? !getName().equals(course.getName()) : course.getName() != null) return false;
        if (getLikes() != null ? !getLikes().equals(course.getLikes()) : course.getLikes() != null) return false;
        return getRegistrations() != null ? getRegistrations().equals(course.getRegistrations()) : course.getRegistrations() == null;

    }

    @Override
    public int hashCode() {
        int result = getId() != null ? getId().hashCode() : 0;
        result = 31 * result + (getName() != null ? getName().hashCode() : 0);
        result = 31 * result + (getLikes() != null ? getLikes().hashCode() : 0);
        result = 31 * result + (getRegistrations() != null ? getRegistrations().hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Course{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", likes=" + likes +
                ", registrations=" + registrations +
                '}';
    }

    public Course() {
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Student> getLikes() {
        return likes;
    }

    public void setLikes(Set<Student> likes) {
        this.likes = likes;
    }

    public void setRegistrations(Set<CourseRegistration> registrations) {
        this.registrations = registrations;
    }

    public Set<CourseRegistration> getRegistrations() {
        return registrations;
    }
}

CourseRegistration.java

@Entity
@Table(name = "course_registration")
public class CourseRegistration {

    @Id
    @Column(name = "id")
    private Long id;

    @ManyToOne
    @JoinColumn(name = "student_id")
    private Student student;

    @ManyToOne
    @JoinColumn(name = "course_id")
    private Course course;

    public CourseRegistration() {
    }

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof CourseRegistration)) return false;

        CourseRegistration that = (CourseRegistration) o;

        if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
        if (getStudent() != null ? !getStudent().equals(that.getStudent()) : that.getStudent() != null) return false;
        return getCourse() != null ? getCourse().equals(that.getCourse()) : that.getCourse() == null;

    }

    @Override
    public int hashCode() {
        int result = getId() != null ? getId().hashCode() : 0;
        result = 31 * result + (getStudent() != null ? getStudent().hashCode() : 0);
        result = 31 * result + (getCourse() != null ? getCourse().hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "CourseRegistration{" +
                "id=" + id +
                ", student=" + student +
                ", course=" + course +
                '}';
    }

}

最佳答案

我已经构建了您的代码,发现此问题是由于 lombok 生成的 hashCode()/equeals()toString() 方法

        at model.Student.hashCode(Student.java:13)
        at java.util.HashMap.hash(HashMap.java:339)
        at java.util.HashMap.put(HashMap.java:612)
        at java.util.HashSet.add(HashSet.java:220)
        at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
...
...
...
        at model.Course.hashCode(Course.java:13)
        at java.util.HashMap.hash(HashMap.java:339)
        at java.util.HashMap.put(HashMap.java:612)
        at java.util.HashSet.add(HashSet.java:220)

我已经删除了所有lombok注释(将评级字段添加到数据库中),结果是:

[Student{id=123, name='Manu', likedCourses=[Course{id=224, name='Course2'}, Course{id=223, name='Course1'}], registrations=[CourseRegistration{id=1, rating=1}, CourseRegistration{id=2, rating=1}]}, Student{id=124, name='Susan', likedCourses=[Course{id=223, name='Course1'}], registrations=[CourseRegistration{id=3, rating=1}]}, Student{id=125, name='Jacob', likedCourses=[Course{id=224, name='Course2'}, Course{id=223, name='Course1'}], registrations=[CourseRegistration{id=4, rating=1}, CourseRegistration{id=5, rating=1}]}, Student{id=126, name='Mathew', likedCourses=[Course{id=224, name='Course2'}, Course{id=223, name='Course1'}, Course{id=226, name='Course4'}], registrations=[CourseRegistration{id=6, rating=1}, CourseRegistration{id=8, rating=1}, CourseRegistration{id=7, rating=1}]}, Student{id=127, name='Sunny', likedCourses=[], registrations=[]}]

关于java - 在 OneToMany 和 ManyToMany 映射中获取 StackOverflow,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60655267/

相关文章:

java - org.hibernate.validator.engine.ConfigurationImpl.getDefaultParameterNameProvider()Ljavax/validation/ParameterNameProvider;

java - 如何确保使用 Hibernate 更新的值在我阅读后没有被更改?

java - @Column 中 nullable=true 的 Hibernate 处理

Java 文件上传到 S3 - 应该多部分加速吗?

java - CompletableFuture : proper way to run a list of futures, 等待结果并处理异常

java - 选择元素 Jsoup 最里面的子元素

java - 如何在 Java 中编辑 html 字符串中的标签

java - 使用 StreamSupport 库时 Dex 失败

java - 我的 Java 程序如何处理 JS 文件以提取函数名称?

ruby-on-rails - docker-compose 中的 OpenJDK