- это ожидаемое поведение?
Да, это так.
Если ответ № 1 - «да», то я улавливаю исключение. Как возможно, что Spring знает, что было сгенерировано исключение?
Когда происходит исключение, Spring будет отмечатьВаша транзакция как rollbackOnly
.Таким образом, даже когда вы перехватываете свое исключение, в конце вашего метода ваша транзакция все еще откатывается.
В вашем случае я не понимаю, почему вы используете @Transaction
, так как вы хотите зафиксировать независимо от исключенияпроисходит.
Редактировать
Когда вы используете транзакцию с БД, вызов транзакции делегируется EntityManager.
Посмотрите на AbstractEntityManagerImpl#handlePersistenceException
:
@Override
public void handlePersistenceException(PersistenceException e) {
if ( e instanceof NoResultException ) {
return;
}
if ( e instanceof NonUniqueResultException ) {
return;
}
if ( e instanceof LockTimeoutException ) {
return;
}
if ( e instanceof QueryTimeoutException ) {
return;
}
try {
markForRollbackOnly();
}
catch ( Exception ne ) {
//we do not want the subsequent exception to swallow the original one
LOG.unableToMarkForRollbackOnPersistenceException(ne);
}
}
При возникновении исключения EntityManager помечает вашу транзакцию как rollbackOnly
до того, как выбрасывает исключение, которое вы хотите перехватить.
После того, как исключение перехватывается в вашей службе, AbstractPlatformTransactionManager
попытается выполнить фиксацию (поскольку, как вы знаете, там не обнаружено исключений), но EntityManager отказывается от фиксации, поскольку обнаруживает, что транзакция помечена как только для отката.
Если вы прочитали исключение, выбудет выглядеть примерно так:
javax.persistence.RollbackException: транзакция, помеченная как rollbackOnly