0

コード レビュー フォーラムで同様の質問をしましたが、ここでその質問をするように提案されました。synchronized以下のWebメソッドのキーワードについて疑問に思っています。はスレッド プールから呼び出されるためsetPerson(つまり、別のスレッドから呼び出すことができる)、何らかの方法で同期化する必要があります。クライアントがメソッドに対してSOAPコールを実行しているときに、EclipseLinkによってスレッド・プールが使用されます。私の質問は、Web メソッドを作成するのが良い方法なのか、それともsynchronized同期を行うことができるのかということem.lock(person, WRITE)です。

@Override
public synchronized void setPerson(Person person) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersonLibPU");            
    EntityManager em = emf.createEntityManager(); 
    if(!em.getTransaction().isActive()) {
       em.getTransaction().begin();
    }
    try {
         person.setPersonId(getLastInsertedId() + 1); // Get the last inserted ID and increment it by 1
         em.merge(person);
         em.getTransaction().commit();  
         emf.getCache().evict(Person.class);                    
    } catch (Exception ex) {
         if(em.getTransaction().isActive())
            em.getTransaction().rollback();
    } finally {
        em.close();
    }
}

EDIT
上記のコードに、人物オブジェクトの主キー値を設定する行をもう1つ追加しました。これが同期の目的であり、共有 Java オブジェクトの場合ではありません。2 つのスレッドが同じ主キーを取得できないように、同期する必要があります。

4

1 に答える 1

1

間違った質問をしている可能性があります。ここでは同期は役に立ちません。同時実行性に関する唯一の懸念事項はgetLastInsertedId()次のとおりです。2 つのメソッドが同じ値を取得して、その ID を持つインスタンスを永続化しようとすることは望ましくありません。

同期setPersonは、それがPerson.

可能であれば、基礎となるデータストアの自動インクリメント機能を使用してください。ORM ソリューションがコンテキスト全体の ID 割り当てを実行することに失敗しましたか? 最後の手段は、同期できgetNextId、インクリメントされた値を返すメソッドを持つことです。これにより、データベース内で不連続な ID シーケンスが発生する可能性があります (永続化操作が成功したかどうかはわかりません) が、これによりロックの範囲が縮小されます。getNextId

JB Nizet が指摘しているように、ID の割り当てを永続化し、このデータ ストアのすべてのクライアントが利用できる何らかの方法で利用できるようにする必要があります。アプリケーション永続インスタンスのインスタンスが 2 つある場合は、Personそれらが ID アロケータを共有していることを確認する必要があります。

于 2012-06-25T08:12:21.650 に答える