web-dev-qa-db-ja.com

コレクションorg.hibernate.HibernateExceptionへの共有参照が見つかりました

私はこのエラーメッセージを受け取りました:

エラー:コレクションへの共有参照が見つかりました:Person.relatedPersons

addToRelatedPersons(anotherPerson)を実行しようとしたとき:

person.addToRelatedPersons(anotherPerson);
anotherPerson.addToRelatedPersons(person);

anotherPerson.save();
person.save();

私のドメイン:

Person {

 static hasMany = [relatedPersons:Person];

}

なぜこれが起こるのか?

55
nightingale2k1

同じコレクション参照(つまり、コレクションの等価性とは対照的なコレクションID)を共有する複数のエンティティインスタンスを永続化しようとすると、Hibernateはこのエラーを表示します。

コレクション要素ではなく、同じコレクションを意味することに注意してください。つまり、relatedPersonspersonの両方のanotherPersonは同じでなければなりません。おそらく、エンティティがロードされた後にそのコレクションをリセットしていますか?または、両方の参照を同じコレクションインスタンスで初期化しましたか?

60
ChssPly76

同じ問題がありました。私の場合、問題は誰かがBeanUtilsを使用して1つのエンティティのプロパティを別のエンティティにコピーすることでした。そのため、同じコレクションを参照する2つのエンティティを持つことになりました。

この問題の調査に少し時間を費やしたことを考えると、次のチェックリストをお勧めします。

  • entity1.setCollection(entity2.getCollection())getCollectionなどのシナリオを探してください。コレクションへの内部参照が返されます(getCollection()がコレクションの新しいインスタンスを返す場合、心配する必要はありません)。

  • clone()が正しく実装されているかどうかを確認してください。

  • BeanUtils.copyProperties(entity1, entity2)を探します。

49
dgt

練習の説明。オブジェクトを保存しようとすると、例えば:

Set<Folder> folders = message.getFolders();
   folders.remove(inputFolder);
   folders.add(trashFolder);
   message.setFiles(folders);
MESSAGESDAO.getMessageDAO().save(message);

更新されたオブジェクトを親オブジェクトに設定する必要はありません。

message.setFiles(folders);

次のように親オブジェクトを簡単に保存します。

Set<Folder> folders = message.getFolders();
   folders.remove(inputFolder);
   folders.add(trashFolder);
   // Not set updated object here
MESSAGESDAO.getMessageDAO().save(message);
5
Mirimas

このエラーの原因をオンラインで読むと、hibernate bugworkaroundそれが機能しているように見える、それは置くことです:

session.clear()

データを取得した後、コミットして閉じる前にクリアする必要があります。例を参照してください。

//getting data
SrReq sr = (SrReq) crit.uniqueResult();
SrSalesDetailDTO dt=SrSalesDetailMapper.INSTANCE.map(sr);
//CLEAR            
session.clear();
//close session
session.getTransaction().commit();
session.close();
return dt;

データベースへの選択、更新または挿入にこのソリューションを使用していますが、このソリューションが機能するか、問題を引き起こす可能性があるかわかりません

私の問題はこれの100%に等しい: http://www.progtown.com/topic128073-hibernate-many-to-many-on-two-tables.html

4
Diego87

私の場合、他のクラスからコードをコピーして貼り付けていたので、ゲッターコードが正しく書かれていないことに気付きませんでした。

@OneToMany(fetch = FetchType.LAZY, mappedBy = "credito")
public Set getConceptoses() {
    return this.letrases;
}

public void setConceptoses(Set conceptoses) {
    this.conceptoses = conceptoses;
}

すべての参照conceptosesしかし、getを見るとletrases

2
John Lopez

私も同じ問題を抱えていました。誰かがBeanUtils.copyProperties(source, target)を使用しました。ここでは、ソースとターゲットの両方が、属性として同じコレクションを使用しています。

だから、次のようにディープコピーを使用しました。

Java-ArrayListおよびHashSetのディープコピー)でコレクションを複製する方法

1
raji

アプリケーションで同様の例外に直面しました。スタックトレースを調べたところ、FlushEntityEventListenerクラス内で例外がスローされたことが明らかになりました。

Hibernate 4.3.7では、MSLocalSessionFactory BeanはeventListenersプロパティをサポートしなくなりました。したがって、個々のHibernateセッションBeanからサービスレジストリを明示的にフェッチし、必要なカスタムイベントリスナーを設定する必要があります。

カスタムイベントリスナーを追加するプロセスでは、対応するデフォルトのイベントリスナーがそれぞれのHibernateセッションから削除されていることを確認する必要があります。

デフォルトのイベントリスナーが削除されない場合、同じイベントに対して登録された2つのイベントリスナーのケースが発生します。この場合、これらのリスナーを反復処理している間、最初のリスナーに対してセッション内のコレクションに到達済みのフラグが付けられ、2番目のリスナーに対して同じコレクションを処理している間にこのHibernate例外がスローされます。

そのため、カスタムリスナーを登録するときに、対応するデフォルトリスナーがレジストリから削除されることを確認してください。

0
Dinesh Angolkar