2016-11-19 110 views
2

我想創建雙向的學生紀律關係。任何事情都可以正常工作,直到我將用戶註冊爲紀律。現在我得到無限遞歸。休眠無限循環遞歸在多對多的關係中

類看起來是這樣的:出現

//Student.java 
@Entity 
@Table(name = "students") 
public class Student { 
    @NotNull 
    @Id 
    @Column(name = "STUDENT_ID") 
    private String id; 
    private String name; 
    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    @JoinTable(name = "students_disciplines", joinColumns = @JoinColumn(name = "STUDENT_ID"), inverseJoinColumns = @JoinColumn(name = "DISCIPLINE_ID")) 
    @JsonSerialize(using = NestedDisciplineSetSerializer.class) 
    private Set<Discipline> disciplines = new HashSet<>(); 
    //Getters, Setters 
} 
//NestedDisciplineSetSerializer.java 
public class NestedDisciplineSetSerializer extends JsonSerializer<Set<Discipline>> { 
    @Override 
    public void serialize(Set<Discipline> value, JsonGenerator jgen, SerializerProvider p) throws IOException, JsonProcessingException { 
     jgen.writeStartArray(); 
     for (Discipline s : value) { 
      jgen.writeStartObject(); 
      jgen.writeStringField("name", s.getName()); 
      jgen.writeNumberField("id", s.getId()); 
      jgen.writeBooleanField("recommended", s.isRecommended()); 
      jgen.writeEndObject(); 
     } 
     jgen.writeEndArray(); 
    } 
} 
//Discipline.java 
@Entity`enter code here` 
@Table(name = "disciplines") 
public class Discipline { 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Id 
    @Column(name = "DISCIPLINE_ID") 
    private int id; 
    @NotNull 
    private String name; 
    @NotNull 
    private int credits; 
    private String annotation; 
    private boolean recommended; 
    @ManyToMany(mappedBy = "disciplines", fetch = FetchType.EAGER) 
    @JsonSerialize(using = NestedStudentSetSerializer.class) 
    private Set<Student> students = new HashSet<>(); 
    //Getters, Setters 
} 
//NestedStudentSetSerializer.java 
public class NestedStudentSetSerializer extends JsonSerializer<Set<Student>> { 
    @Override 
    public void serialize(Set<Student> value, JsonGenerator jgen, SerializerProvider p) throws IOException, JsonProcessingException { 
     jgen.writeStartArray(); 
     for (Student s : value) { 
      jgen.writeStartObject(); 
      jgen.writeStringField("name", s.getName()); 
      jgen.writeStringField("id", s.getId()); 
      jgen.writeEndObject(); 
     } 
     jgen.writeEndArray(); 
    } 
} 

錯誤被加載時設置Student s = sDao.findOne(id);

試圖在這裏搜索後,但沒能找到合適的解決方案。任何取得相同結果的東西。

Error log

回答

2

org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:430) 〜[冬眠核-5.0.11.Final.jar:5.0.11.Final] 在truelecter.practproekt 。實體。 Discipline.hashCode(Discipline.java:31) 〜[classes /:na] at java.util.HashMap.hash(HashMap.java:338)〜[na:1.8.0_91] at java.util。 HashMap.put(HashMap.java:611)〜[na:1.8.0_91] at java.util.HashSet.add(HashSet.java:219)〜[na:1.8.0_91] at java.util.AbstractCollection。的addAll(AbstractCollection.java:344) 〜[NA:1.8.0_91] 在org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:327) 〜[hibernate-core-5.0.11.Final。 jar:5.0.11.Final] at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:234) 〜[hibernate-core-5.0.11.Final.jar:5.0.11.Final ] at ... org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:430) 〜[hibernate-core-5.0.11.Final.jar:5.0.11.Final] at truelecter.practproekt。實體。 Student.hashCode(Student.java:29)〜[classes /:na] at java.util.HashMap.hash(HashMap.java:338)〜[na:1.8.0_91] at java.util.HashMap .put(HashMap.java:611)〜[na:1.8.0_91] at java.util.HashSet.add(HashSet.java:219)〜[na:1.8.0_91] at java.util.AbstractCollection.addAll (AbstractCollection.java:344)〜

我的印象中,爲DisciplineStudent實體hashcode()方法實現使用兩個實體。
也許我錯了,它在堆棧跟蹤中不是很清楚。
你是如何爲你的實體定義equals()hashcode()方法的?
假設實體A和實體B具有雙向關係。
如果equals()/hashcode()實現實體A 的調用上本身的實體A領域調用equals()/hashcode()實體Bequals()/hashcode(),你有一個週期。
鑑於你的錯誤。

此外,即使你通過確保只有兩個一個是指其他在equals()/hashcode()/toString()下調週期,你應該調用與謹慎的實體關係的equals()/hashcode()/toString方法。
它可能會對性能產生實際影響。如果Hibernate會話打開,它可能確實執行您不希望的查詢。

+0

謝謝回答,問題是我已經用於簡化生成getter和setter的龍目島庫。對於創建循環的兩個實體,它都是@Data annotation生成的hashCode()方法。歡迎您致電: – TrueLecter

+0

謝謝您的反饋。 – davidxxx

1

兩側的具有預先抓取類型。這意味着對於你加載的每個學生,Hibernate將加載相關的每個學科,並且對於每個學科,它將加載它的學生。這是你的循環。您可以更改一側的獲取類型(兩者都更好),對於FetchType.LAZY。這樣做,學生的紀律只會在您訪問列表時加載。