2

私が見た JPA/Hibernate エンティティ Bean クラスのほとんどの例では、明示的な同期が行われていないようです。ただし、トランザクションを構築するコンテキストで、これらのオブジェクトに対して getter/setter を呼び出すことは可能です。また、これらのメソッドを複数のスレッドで呼び出すこともできます (ただし、これは異常で奇妙なことかもしれません)。

複数のスレッドにまたがって構築されている場合、オブジェクトの状態への変更が失われる可能性があるようです。これは悲しいことです。

では、同期のベスト プラクティスを除外することはありますか? Hibernate のインストルメント化されたコードは適切な同期を処理していますか?

例として:

@Entity
public class Ninja {
  @Id @GeneratedValue
  private Long id;

  @Column 
  private String name;

  @Column
  private int throwingStars;

  public Ninja() {}
  public int getThrowingStars() { return throwingStars; } 
  public void addThrowingStar() { throwingStars += 1; }
}

手裏剣のメソッドには同期が必要ですか? 私の忍者が手裏剣を失うことは絶対に望んでいません。

4

5 に答える 5

3

私の意見では、スレッド間でドメイン オブジェクトを共有することは絶対にしないでください。実際、このようなデータは保護する必要があるため、通常、スレッド間で共有することはほとんどありません。私はいくつかの大規模/高性能システムを構築しましたが、このルールを破る必要はありませんでした. 作業を並列化する必要がある場合は並列化しますが、ドメイン オブジェクトのインスタンスを共有することは避けてください。各スレッドは、データベースからデータを読み取り、オブジェクトを変更/作成して操作し、トランザクションをコミット/ロールバックする必要があります。ワーク パス イン/アウトは、通常、値/読み取り専用オブジェクトである必要があります。

于 2009-04-16T21:15:44.957 に答える
2

「そして、これらのメソッドが複数のスレッドで呼び出される可能性があります (ただし、それは異常で奇妙なことかもしれませんが)。」

JPAの経験があまりないので、休止状態についてのみ話すことができます。set を呼び出すオブジェクトは、get を呼び出すオブジェクトと必ずしも同じではありません。Hibernate がオブジェクトをロードしているときに、set* メソッドを呼び出すようになり、残りの時間は get (およびスレッド) が呼び出します。

繰り返しになりますが、(ライター スレッドで) 既存のオブジェクトを変更してから再度保存する場合は、オブジェクトへのアクセスを保護する必要があります (他のリーダー/ライター スレッドがダーティ データを読み取らないようにするため)。

于 2008-10-08T17:52:45.447 に答える
1

オブジェクトはおそらく 2 つのスレッドで同じではありません。スレッドがセッション ファクトリを使用して db にアクセスすると仮定すると、セッションから取得したオブジェクトは「独立した」ものとして表示されます (セッションにない限り、hibernate は get() ごとに「新しい」オブジェクトを作成すると思います)。

スターの質問については、2 人が DB から同じ行をフェッチする場合も同じです。DB の「ACID」プロパティにより、各操作がアトミックであることを確認できるため、スレッド t1 で忍者からスターを削除してcommit すると、スレッド t2 は、t1 のコミットされた値を読み取ります。

または、Hibernate に T1 の関連する忍者の行をロックするように依頼することもできます。これにより、T2 が行を要求しても、T1 がコミットまたは中止するまで待機する必要があります。

于 2008-10-14T13:08:35.940 に答える
0

問題のベスト プラクティスは、楽観的ロックです。

Java Persistence API (JPA) 仕様 (第 3.4.1 章) から:

オプティミスティック・ロックは、エンティティーの状態が読み取られて以来、介在するトランザクションがそのエンティティー状態のデータを更新していない場合にのみ、エンティティーの状態に対応するデータベース・データへの更新が確実に行われるようにするために使用される手法です。これにより、そのデータに対する更新または削除がデータベースの現在の状態と一致し、その間の更新が失われないことが保証されます。

クラスに @Version アノテーションを追加し、DB テーブルに列を追加する必要があります。

于 2009-03-25T16:59:23.900 に答える
0

JPA/Hibernate エンティティは POJO です。Hibernate および JPA プロバイダーは、実行時のセマティクスを変更しません。

したがって、単純な POJO で同時実行の問題が発生する場合は、エンティティでも問題が発生します!

私が見たすべてのシステムで、ドメイン モデルはスレッドセーブではなく、エンティティ インスタンスは複数のスレッドからアクセスされません。

ただし、同じエンティティの複数のインスタンスを同時に持つことができます。この場合、同期は DB を介して行われます。ここでのパターンは楽観的ロックと悲観的ロックです。Hibernate と JPA は、これらのパターンの実現に役立ちます。

于 2009-02-18T12:34:36.870 に答える