私はJPAとHibernateの新機能です(私は勉強しています!)、私は些細な解決策を見つけることができないという問題を抱えています。だからここにある。Hibernate:遅延初期化と壊れたハッシュコード/矛盾の一致
私はちょっと次のようなエンティティがあります。
@Entity
@Table(name = "mytable1")
public class EntityOne {
// surrogate key, database generated
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
// business key
@Column(name = "identifier", nullable = false, unique = true)
private String identifier;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
@JoinColumn(name = "twoId", nullable = false)
private EntityTwo two;
@OneToMany(mappedBy = "entityOne", fetch = FetchType.EAGER,
cascade = {CascadeType.ALL}, orphanRemoval = true)
private Set<EntityThree> resources = new HashSet<>();
// getters/setters omitted
@Override
public int hashCode() {
// the business key should always be defined (through constructor/query)
// if this is null the class violates the general hashcode contract
// that the integer value returned must always be the same
Assert.notNull(identifier);
// a dirty alternative would be:
// if(identifier==null) return 0;
return identifier.hashCode();
}
@Override
public boolean equals(Object o) {
return o instanceof ResourceGroup
&& ((ResourceGroup) o).identifier.equals(identifier);
}
}
私のプロジェクトは春JPAに設定されているので、私は私のいくつかの@Transactional
メソッドを持っていると私はスキャンサービスクラスでCrudRepository<EntityOne,Long>
を注入しているが私のJPAドメインとサービスパッケージとトランザクション。
サービスメソッドの1つが、リポジトリのfindAll()
メソッドを呼び出し、EntityOne
のリストを返します。
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
は、私はこのオブジェクトを初期化していると役に立つかもしれないと思ったので、私は熱心に怠惰からフェッチタイプを切り替える:私は明らかにスローされ、
two
のためのゲッターにアクセスしようとしない限り、すべてが正常に動作します。しかし、私は次のことを得ることを行った場合:
java.lang.IllegalArgumentException: [Assertion failed] - this argument is required; it must not be null
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.util.Assert.notNull(Assert.java:123)
at my.pkg.domain.EntityOne.hashCode(ResourceGroup.java:74)
at java.util.HashMap.hash(HashMap.java:351)
at java.util.HashMap.put(HashMap.java:471)
at java.util.HashSet.add(HashSet.java:217)
at java.util.AbstractCollection.addAll(AbstractCollection.java:334)
at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:346)
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:243)
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:233)
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:209)
at org.hibernate.loader.Loader.endCollectionLoad(Loader.java:1149)
//...
私は簡単にHibernateのソースコードを見て、彼らのビジネスキーが初期化される前にセットで私EntityOne
オブジェクトを置くしようとしているように見えます。私の解釈は正しいのですか?これを回避する方法はありますか?私は何か信じられないほどばかなことをしていますか?
私は
EDITあなたの助けに感謝:私はちょうど私がここで理解しようとしていることは、ベストプラクティスは、特にJPAに関してあるとを休止するものであることを明確にしたいです。これが普通のPOJOならば、私は識別子フィールドを最終的に作ることができました(私は実際にはクラス全体を不変にして安全です)。私はJPAを使っているので、これを行うことはできません。だから質問:あなたはhashCode契約に違反していますか? Hibernateはこの違反をどのように処理しますか?これを一般的に行うJPA推奨の方法は何ですか?ハッシュベースのコレクションを取り除き、代わりにリストを使うべきですか?
ジョバンニ
私はすべての関係する 'Set'フィールドの初期値を' new HashMap() 'の代わりに'新しいLinkedHashMap() 'に置き換えて動作させました。それは奇妙ではありませんか? –