2016-11-19 11 views
2

私は双方向の学生 - 規律関係を作成したいと思います。私が訓練するためにユーザーを登録するまで、何もうまく動作します。今私は無限の再帰を得ている。多対多関係のHibernate無限ループ再帰

クラス次のようになります。

//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 〜[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] at 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] java.util.HashMap.hash(HashMap.java:338)〜[na:1.8.0_91]の 〜[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が双方向の関係にあるとします。
エンティティAequals()/hashcode()実装は、それ自体が実体Aフィールド上equals()/hashcode()を呼び出すエンティティBフィールド上equals()/hashcode()を呼び出した場合は、サイクルを持っています。
あなたのエラーです。

さらに、両者の一方がequals()/hashcode()/toString()を参照するようにしてサイクルを切断しても、エンティティリレーションシップのメソッドは慎重に呼び出す必要があります。
パフォーマンスに大きな影響を与える可能性があります。 Hibernateセッションが開かれていると、実際には期待していないクエリが実行される可能性があります。

+0

答えていただきありがとうございます。ゲッターとセッターの生成を簡略化するために使用していたlombokライブラリに問題がありました。 @Dataアノテーションは、ループを作成した両方のエンティティのhashCode()メソッドを生成しました。 – TrueLecter

+0

あなたは大歓迎です。 – davidxxx

1

両方イーガーフェッチ・タイプを持っています。これは、あなたがロードする各生徒のために、Hibernateはすべての規律関係をロードし、各規律ごとに生徒をロードすることを意味します。これがあなたのループです。あなたはFetchType.LAZYのために、片方のフェッチタイプを変更することができます(どちらも優れています)。そうすることで、リストにアクセスすると、学生の訓練が読み込まれます。