3

我正在尝试在 JavaEE 中使用“SELECT FOR UPDATE NOWAIT”(使用 JPA)。我就是这样做的:

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

这很顺利,除了一件事:如果失败(无法获取锁),则抛出 PessimisticLockException 而不是 LockTimeoutException(如果设置了任何其他正超时则抛出),这会导致事务(JTA 事务)标记为回滚。

我已经尝试使用本机查询,但它产生了相同的结果。
我正在使用带有 EclipseLink 的 Weblogic 12.1(也尝试过 TopLink,没有区别)。

当执行失败时,是否有任何方法可以执行“SELECT FOR UPDATE NOWAIT”而不会在 JavaEE 中将 JTA 事务标记为回滚?

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 回答