0

10を実行して負荷テストをSoap UI実行すると、デッドロックが発生します。すべてのスレッドが、OpenJPAエンティティマネージャーのpersitsメソッドを呼び出すWebサービスに10のリクエストを送信します。

次に、単一の要求を実行しています。すべてが正常に終了しますが、マルチスレッド環境ではデッドロックが発生します。

私が得ているエラーは次のとおりです。

Deadlock found when trying to get lock; try restarting transaction {prepstmnt 12796448 UPDATE Assessment SET dateCompleted = ? WHERE id = ? [params=?, ?]} [code=1213, state=40001]

デッドロックでクラッシュしているメソッドは次のとおりです。

@Override
public AssessmentKey update(AssessmentKey assessmentKey) {
    OpenJPAEntityManager openJpaEntityMgr = OpenJPAPersistence.cast(entityManager);
    for (Assessment assessment : assessmentKey.getAssessments()) {
        if (!entityManager.contains(assessment) && !openJpaEntityMgr.isDetached(assessment)) {
            LOGGER.debug("Persisting {}", assessment);
            entityManager.persist(assessment);
        }
    }
    return entityManager.merge(assessmentKey);
}

AssessmentはOpenJPAのエンティティであり、JPAアノテーションを含む通常のエンティティです。そのコードが必要な場合は、それを求めてください。

デッドロックがどのように発生しているのか、それらを解決する方法がここに記載されていることを理解しました。しかし、ORMでそれらを解決する方法私は答えを見つけることができません。

私のpersistence.xmlファイルは次のようになります。

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
    <persistence-unit name="com.groupgti.esb.online.tests">
        <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
        <class>com.groupgti.esb.assessments.model.jpaimpl.Assessment</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <validation-mode>NONE</validation-mode>
        <properties>
            <property name="openjpa.Log" value="slf4j"/>
            <property name="openjpa.DataCache" value="false"/>
            <property name="openjpa.ReadLockLevel" value="none"/>
            <property name="openjpa.WriteLockLevel" value="pessimistic-write"/>
            <property name="openjpa.LockTimeout" value="10000"/>
            <property name="openjpa.RuntimeUnenhancedClasses" value="unsupported"/>
        </properties>
    </persistence-unit>
</persistence>

アプリケーション全体で使用Springされ、トランザクションが実行されるクラスにはマークが付けられ@Transactionalます。ORMでこのデッドロックの問題を解決するにはどうすればよいですか?

編集:

とのAssessmentKey関係がありAssessmentます:

@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, mappedBy = "assessmentKey")
private List<Assessment> assessments = new ArrayList<Assessment>();

そして、Assessment AssessmentKeyこのように見えます:

@ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@Index
@Column(nullable = false)
@ForeignKey
private AssessmentKey assessmentKey;
4

1 に答える 1

1

AssessmentKeyAssessmentOneToMany双方向の関係です。OneToManyとの両方のManyToOne注釈にはCascadeType.PERSISTと その他があります。

ポイントは:

EntityManagerpersistAssessmentの場合AssessmentKeyも永続化されます。再度永続化またはマージする必要がありますAssessmentKey

次のようにORマッピングを提案させてください:

AssessmentKey.java

@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, 
           mappedBy = "assessmentKey", orphanRemoval=true)
private List<Assessment> assessments;

アセスメント.java

@ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.REFRESH})
@JoinColumn(name = "ASSESSMENT_ID", referencedColumnName = "ID")
private AssessmentKey assessmentKey;

DB操作

@Override
public AssessmentKey update(AssessmentKey assessmentKey) {
    OpenJPAEntityManager openJpaEntityMgr = OpenJPAPersistence.cast(entityManager);
    // there may be your operation
    return entityManager.merge(assessmentKey);
}

Assessment現在のAssessmentKeyオブジェクトの値は次のようになると思います

On System                               |   In Existing Database
ID      Description                     |   ID      Descrition
1001    AAA         => No Changes       |   1001    AAA
1002    BBB         => Need to update   |   1002    BB
null    DDD         => Need to add      |   1003    CCC     => need to remove.

EntityManager が merge すると、上記のデータ構造で述べたようにAssessmentKeyEntityManager意志がすべてのプロセスを実行します。Assessment

注:注釈 で確認orphanRemoval=trueしてください。OneToMany

于 2012-10-23T15:24:18.130 に答える