2009-07-10 2 views
2

Webアプリケーションで使用するときに問題を引き起こすJava DAOのメソッドで 'synchronized'キーワードを使用していますか?Java DAOで同期を使用していると問題が発生しますか?

ここに示すように、リソースの競合を避けるためにメソッドを同期させる必要があるマルチスレッドのスタンドアロンアプリケーションがあるので、私は尋ねます。私は心配です何

java.util.concurrent.ExecutionException: javax.persistence.PersistenceException: org.hibernate.HibernateException: Found shared references to a collection: com.replaced.orm.jpa.Entity.stuffCollection 

があること人々のかなりの数がしようとすると、同期方法はブロックし、アプリケーション全体を遅くするアプリケーションを使用する場合。

私は、スプリングで注入されたJPAエンティティマネージャファクトリを使用しています。これは、DAOにエンティティマネージャを提供します。私は技術的にDAOレイヤーを削除し、クラスでエンティティマネージャーファクトリを直接呼び出すことができますが、DAOが提供する分離を楽しむことができます。

スレッド間で接続されたエンティティORMオブジェクトを渡さないように非常に注意しています。私は、DAOにアクセスする際にリソースの競合エラーが発生すると推測しています。私は、複数のスレッドが同時に進行していて、非原子的な方法でデータベースを永続化または読み込みしようとしていると思います。

この場合、DAOを使用して、より多くの害を及ぼしていますか?


私が質問から外した大きな情報は、DAOはシングルトンではないということです。もし私がその詳細を含めるだけでも十分に分かりやすいと思っていたなら、おそらく最初にその質問をしなかったでしょう。

私が正しく理解していれば、Springはそれを使用するクラスごとにDAOクラスの新しいインスタンスを作成します。したがって、バッキングエンティティマネージャは各スレッドに対して一意でなければなりません。エンティティマネージャを共有していないのは、Rob Hが答えたように、ここで重要なことです。

しかし、同期を解除するとエラーが発生する理由はわかりません。


このthreadによると、@PersistenceContextアノテーションはスレッドセーフSharedEntityManagerを作成します。したがって、シングルトンDAOを作成できるはずです。

+0

あなたは、同期を使用する理由と、どのような種類の「リソースの競合」を参照しているのでしょうか? – skaffman

答えて

2

スレッド間でエンティティオブジェクトを共有していないとします。それは良い。しかし、スレッド間でEntityManagerオブジェクト(またはセッションオブジェクトが共有されていないこと)も確認する必要があります。 Springのようなフレームワークは、スレッドローカル変数にセッションを格納することによって自動的にこれを管理します。フレームワークの助けを借りずに独自のDAOをコーディングする場合は、共有することを避けるために注意を払う必要があります。

これを実行すると、会話状態のいずれもスレッド間で共有されないため、DAOメソッドを同期する必要はありません。これは、並行性の高いWebアプリケーションにとって非常に重要です。別の方法として、同じDAOインスタンスをすべて共有していると仮定して、一度に1つのスレッドだけがDAOにアクセスできるようにすることです。スループットが悪い

+0

Springが必要とするクラスに注入されたエンティティマネージャへの直接アクセスに戻って、フレームワークに機能させる方が良いと思いますか? –

+1

"エンティティマネージャへの直接アクセス"とは何を意味するのかよくわかりません。通常、DAOでのみエンティティマネージャにアクセスします。 DAOがJpaDaoSupportのサブクラスを持つことで、スレッドローカルエンティティマネージャに簡単にアクセスできます。 (詳細は、Springのドキュメントを参照してください。)次に、Springを使用してDAOをビジネスサービスオブジェクトに挿入します。したがって、ビジネスサービスはEMで直接動作することはありません。 –

+0

私はJpaDaoSupportを調べます。私が直接アクセスすることが意味するのは、データベースにアクセスする必要がある各クラスに、スプリングインジェクションマネージャを持つことです。これは、アノテーションで行うのがかなり簡単です。 –

1

スレッドの安全性のために同期が必要な場合は、スレッドの安全性を維持してください。その場合、ブロックは必要です。ブロッキングは、Webアプリケーションの場合に必要とされていない場合は、いずれかをすることができます:あるとして

  • は、パフォーマンス以来、それを残す ヒット には競合が存在しない場合にロックがごくわずかであり、重要でない に入れアカウント データベースにぶつかる費用。
  • 同期レイヤーを スタンドアロンアプリケーションケースに追加して、 が基になる の非同期DAOを保護するように再設計します。

個人的には、私はそれをそのまま残し、リファクタリングする必要があるかどうかを確認します。それまでは、早すぎる最適化を行うだけです。

+0

それは良い点ロビンです。私はまだ持っていない問題を解決しようとするトラップに落ちているかもしれません。私は、私のアプローチが他の人々に大変間違っていないことを確認したかっただけです。 –

関連する問題