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;