Подтвердить что ты не робот

Почему транзакция откатывается в RuntimeException, но не SQLException

У меня есть метод управления Spring для управления вставками базы данных. Он содержит несколько инструкций вставки.

@Transactional
public void insertObservation(ObservationWithData ob) throws SQLException 
{
    observationDao.insertObservation(ob.getObservation());
            // aop pointcut inserted here in unit test
    dataDao.insertData(ob.getData());
}

У меня есть два модульных теста, которые генерируют исключение перед вызовом второй вставки. Если исключение является RuntimeException, транзакция откатывается. Если исключением является SQLException, первая вставка сохраняется.

Я озадачен. Может ли кто-нибудь сказать мне, почему транзакция не откат на SQLException? Может ли кто-нибудь предложить предложение об управлении этим? Я мог поймать SQLException и бросить RuntimeException, но это просто кажется странным.

4b9b3361

Ответ 1

Это определено поведение. Из docs:

Любые RuntimeException триггеры откат, а в любом исключенном исключении нет.

Это обычное поведение во всех API-интерфейсах транзакций Spring. По умолчанию, если a RuntimeException выбрасывается из транзакционного кода, транзакция будет отменена. Если выбрано исключенное исключение (т.е. Не a RuntimeException), транзакция не будет отменена.

Обоснованием этого является то, что классы RuntimeException обычно берутся Spring для обозначения неустранимых условий ошибки.

Это поведение можно изменить по умолчанию, если вы хотите это сделать, но как это сделать, зависит от того, как вы используете API Spring и как вы настраиваете менеджера транзакций.

Ответ 2

Spring широко использует RuntimeExceptions (включая использование DataAccessExceptions для обертывания SQLExceptions или исключений из ORM) для случаев, когда нет восстановления из исключения. Предполагается, что вы хотите использовать проверенные исключения для случаев, когда уровень над сервисом должен быть уведомлен о чем-то, но вы не хотите, чтобы с транзакцией было вмешательство.

Если вы используете Spring, вы можете также использовать свои библиотеки jdbc-wrapping и средство DataAccessException-translating, это уменьшит количество кода, который вам нужно поддерживать, и предоставит более значимые исключения. Кроме того, наличие уровня обслуживания, бросающего исключения для конкретной реализации, является неприятным запахом. Пред-Spring способ состоял в том, чтобы создавать исключения, зависящие от реализации - агностические проверенные исключения, связанные с исключениями для конкретной реализации, что привело к большому количеству занятой работы и раздутой базы кода. Spring позволяет избежать этих проблем.

Если вы хотите знать, почему Spring решил заставить все работать таким образом, вероятно, потому, что они используют AOP для добавления обработки транзакций. Они не могут изменить подпись метода, который они обертывают, поэтому проверенные исключения не являются опцией.