1

作業中の永続化レイヤーのテストをいくつか作成していますが、処理に問題があるという例外が発生しました。これは、で発生しているConcurrentModificationExceptionですorg.hibernate.mapping.Table.cleanseUniqueKeyMap(Table.java:291)
これが次のコード行であることがわかります。

final Map.Entry<String,UniqueKey> uniqueKeyEntry = uniqueKeyEntries.next();

少し調べてみたところ、このスレッドがコレクションを反復処理しているときに、1つのスレッドがこのコレクションを変更したことが例外の原因であることがわかりました。そうは言っても、トラブルシューティングに関する提案が発生する原因となっていることは何もしていないように感じますか?

ところで、私は使用してhibernate 4.1.5います。それが何かをクリアするかどうかのIdk。これが私のテストです:

@Test
public void testCreateMobsterUser() {
   try {            
       final MobsterUserDAO test = new MobsterUserDAO(); //throws exception
       //does stuff w/ return value...

ご覧のとおり、daoを初期化してみます。そのコードを見てみましょう。

public MobsterUserDAO() {
    super(MobsterUser.class);
}

それではあまりわかりませんでしたので、一般的なdaoコンストラクターを見て、そこで問題が発生するかどうかを確認しましょう。

public MobsterBaseHibernateDAO(final Class<T> clazz) {
    this.clazz = clazz;
    //This next line is where the exception is actually occuring
    final EntityManagerFactory factory = Persistence.createEntityManagerFactory("mobsterdb");
    this.manager = (HibernateEntityManager) factory.createEntityManager();
}

Persistance.createEntityManagerFactoryがどのような種類のウサギの穴であるかはわかりませんが、例外が発生する前に実行されるコードの最後の行です。

4

3 に答える 3

3

for-eachループでコレクションを繰り返し、別の場所でコレクションを変更すると、同時変更が発生します。Iterator一般的な解決策の1つは、 for-eachループの代わりに使用することです。または、コレクションをsynchronizedブロックします。

それについては至る所にリソースがあります:

ConcurrentModificationExceptionを回避すると、次のようになります。

  1. リストを配列に変換してから、配列を反復処理できます。このアプローチは、小規模または中規模のリストには適していますが、リストが大きい場合は、パフォーマンスに大きく影響します。

  2. 同期ブロックにリストを配置することにより、反復中にリストをロックできます。このアプローチは、マルチスレッドの利点を失うため、お勧めしません。

  3. JDK1.5以降を使用している場合は、ConcurrentHashMapクラスとCopyOnWriteArrayListクラスを使用できます。これが推奨されるアプローチです。

また:

同時変更例外ConcurrentModificationException
をデバッグする方法は?

于 2012-07-18T04:46:16.657 に答える
2

Hibernateによる内部ハウスキーピング中の例外のように思われるので、私はそれがバグだと思っていました。Googleですばやく検索すると、最近報告されたJIRAが表示されます。

提案された決議がありますが、いつリリースされるかはわかりません。

お役に立てれば!

于 2012-07-18T06:19:27.210 に答える
0

これは、ループがコレクションを通過し、ループ内のどこかで、反復しているコレクションを変更し、何も変更されていないかのようにループを再開しようとするために発生します。

私にも同じことが起こりました:

for(UserJPA jpa : jpaList){
    if(jpa satisfies a condition){
        jpaList.remove(jpa);
    }
}

問題は、繰り返し処理しているリストを変更できないことです。私が選んだ解決策は、元のリストを変更しながら、新しいリスト、つまり元のリストのコピーを作成して、それを反復処理することでした。

List<UserJPA> iterationList = new ArrayList<UserJPA>(jpaList);
for(UserJPA jpa : iterationList){
    if(jpa satisfies a condition){
        jpaList.remove(jpa);
    }
}

お役に立てば幸いです。

于 2016-11-02T12:51:52.583 に答える