JavaEE: "ВЫБРАТЬ ДЛЯ ОБНОВЛЕНИЯ ОБНОВЛЕНИЯ", не отмечая транзакцию JTA для отката при сбое?

Я пытаюсь использовать "SELECT FOR UPDATE NOWAIT" в JavaEE (используя JPA). Вот как я это делаю:

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

Это идет хорошо, за исключением одной вещи: если это не удается (не удалось получить блокировку), то вместо исключения LockTimeoutException (которое выбрасывается, если установлен какой-либо другой положительный тайм-аут) создается исключение PessimisticLockException (которое вызывается транзакцией) быть отмеченным для отката.

Я попытался использовать нативные запросы вместо этого, но это дает тот же результат.
Я использую Weblogic 12.1 с EclipseLink (пробовал также TopLink, без разницы).

Есть ли способ выполнить "SELECT FOR UPDATE NOWAIT", чтобы транзакция JTA не была помечена для отката в JavaEE при сбое выполнения?

1 ответ

Решение

Пожалуйста, зарегистрируйте ошибку и проголосуйте за нее.

Вероятно, вы можете исправить это, создав собственный подкласс OraclePlatform и переопределив isLockTimeoutException().

Вы также можете выполнить запрос как DatabaseQuery, чтобы избежать отката.

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

Используйте приведенный ниже код, чтобы пропустить заблокированную строку. Это альтернатива

выберите * от студента, где идентификатор студента = n для обновления 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();
}
Другие вопросы по тегам