Как я узнаю, что транзакция не удалась и была отменена?

В настоящее время я использую аннотацию spring @transactional для внесения ряда изменений в базу данных. При любом исключении, которое не было создано мной (например, мое предложение UPDATA нарушает ограничения столбцов в таблице), транзакция успешно откатывается. Однако в консоли сообщение об ошибке не выводится.

Я хотел бы обрабатывать такие случаи вручную. Например, я могу захотеть записывать такие события в txt-файл. Мне интересно, есть ли у меня способ поймать такие исключения (или, точнее, иметь прослушиватель для таких событий).

Соответствующий код

@Transactional
public class DefaultFooService implements FooService {
    public Foo getFoo(String fooName) {
        INSERT A ROW
        UPDATE A ROW
    }
}

В приведенном выше коде предположим, что INSERT A ROW выполнено успешно, а UPDATE A ROW не выполнено из-за SQLException (например, из-за нарушения ограничений столбца). В настоящее время сообщение об ошибке не выводится на консоль, если для ведения журнала задано значение INFO. Когда я использую DEBUG, я вижу, что SQLException обнаруживается, и tx откатывается.

Как я могу получить уведомление, когда транзакция не удалась и ее откатили?

======

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


Чтобы проиллюстрировать проблему по-другому. В следующем блоке кода в настоящее время не будет выдано исключение (выведено в стандартный вывод). Как я могу поймать/обработать RuntimeException?

@Transactional
public class DefaultFooService implements FooService {
    public Foo getFoo(String fooName) {
        throw new RuntimeException();
    }
}

person The Yellow    schedule 15.06.2018    source источник
comment
@Dherik Этот вопрос несколько отличается от вопроса о динамической регистрации прослушивателя транзакций с помощью Spring? в том, что я хочу получать уведомления тогда и только тогда, когда моя транзакция не удалась, и я хочу знать, почему она не удалась.   -  person The Yellow    schedule 15.06.2018
comment
правильно. Я удалю свой закрытый голос :)   -  person Dherik    schedule 15.06.2018
comment
Может у вас есть блок catch без printstacktrace()? Если он обнаруживает ConstraintViolation, но нет блока catch, в котором выполняется откат, это означает, что это обрабатывает служебный класс. Вы можете добавить к нему объявление throws и обрабатывать его вне метода.   -  person Carlos López Marí    schedule 15.06.2018
comment
Вы можете установить уровень ведения журнала TRACE в пакете org.springframework.transaction, чтобы получить вывод журналов транзакций Spring.   -  person SrThompson    schedule 15.06.2018


Ответы (1)


Вы можете использовать блоки try-catch для операций с базой данных и делать с информацией об исключениях все, что захотите. Затем, если вы решите, что все еще хотите откатиться, вы можете сгенерировать исключение из блока catch. Или, если вы действительно хотите получить фантазию:

@Transactional(rollbackFor={FancyOwnException.class})

или даже внутри улова вручную:

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
person Alim Özdemir    schedule 15.06.2018
comment
Проблема в том, что это не мое собственное исключение. В случае, представленном выше, генерируется «SQLException», и его нельзя перехватить с помощью блока try and catch. - person The Yellow; 15.06.2018
comment
Вы можете поймать любое исключение, вы имеете в виду, что SQLException обернут Spring/Hibernate. Чтобы проверить catch(DataAccessException e) { if(e.getRootCause() instanceof SQLException) { сделайте свое дело. } } - person Alim Özdemir; 15.06.2018