JavaEE:'SELECT FOR UPDATE NOWAIT'在没有标记JTA事务以便在失败时回滚?

时间:2012-12-03 17:21:42

标签: java-ee jpa locking jta

我正在尝试在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事务标记为回滚?

2 个答案:

答案 0 :(得分:2)

请记录错误并投票支持。

您可以通过创建自己的OraclePlatform子类并覆盖isLockTimeoutException()来修复它。

您还可以将查询作为DatabaseQuery执行以避免回滚。

em.unwrap(Session.class).executeQuery(((JpaQuery)query).getDatabaseQuery())

答案 1 :(得分:0)

使用以下代码跳过锁定的行。这是

的替代
  

从学生ID = n的学生中选择*,以进行不等待更新

如果行已被锁定,则

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();
}