3

JavaEEで「SELECTFORUPDATENOWAIT」を使用しようとしています(JPAを使用)。これが私のやり方です:

props.put("javax.persistence.lock.timeout", 0);
em.find(MyEntity.class, id, LockModeType.PESSIMISTIC_READ, props);

これは1つのことを除いてうまくいきます:これが失敗した場合(ロックを取得できなかった場合)、LockTimeoutException(他の正のタイムアウトが設定されている場合にスローされます)の代わりにPessimisticLockExceptionがスローされ、トランザクション(JTAトランザクション)が発生しますロールバックのマークが付けられます。

代わりにネイティブクエリを使用してみましたが、同じ結果が得られます。
EclipseLinkでWeblogic12.1を使用しています(TopLinkも試してみましたが、違いはありません)。

実行が失敗したときにJTAトランザクションがJavaEEでロールバックのマークを付けられずに、「SELECT FORUPDATENOWAIT」を実行する方法はありますか?

4

2 に答える 2

2

バグを記録して投票してください。

OraclePlatformの独自のサブクラスを作成し、isLockTimeoutException()をオーバーライドすることで、おそらく修正できます。

ロールバックを回避するために、クエリをDatabaseQueryとして実行することもできます。

em.unwrap(Session.class).executeQuery(((JpaQuery)query).getDatabaseQuery())
于 2012-12-04T15:12:21.947 に答える
0

以下のコードを使用して、ロックされた行をスキップします。これはの代替です

select * from student where student id = n for update nowait

行がすでにロックされている場合、findStudntメソッドはエラーをスローします。エラーがない場合は、updateStudentメソッドを呼び出して学生エンティティを更新します。それ以外の場合は、監査のためにエラーをログに記録します。

@Override
public Student findStudent(final Long studentId) {
    TypedQuery<Student> query = getEntityManager().createNamedQuery("from Student s where s.studentId =:studentId", Student.class);
    query.setParameter("studentId", studentId);
    query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
    query.setHint(JAVAX_PERSISTENCE_LOCK_TIMEOUT, ZERO_NUMBER);
    return query.getSingleResult();
}

@Override
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public void updateStudent(Student student) {
    makePersistent(student);
    getEntityManager().flush();
}
于 2019-07-14T08:12:21.927 に答える