我正在尝试在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事务标记为回滚?
答案 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();
}