Spring делает операцию при ошибке перехвата асинхронного транзакционного метода - PullRequest
0 голосов
/ 23 марта 2020

Я прочитал директивы в Spring @Transactional - изоляция, распространение

, но я не понимаю, как появилась эта функция, которую я объясняю: у меня есть асинхронный метод как это

@Transactional(timeout = TRANSACTION_TIMEOUT, propagation = Propagation.REQUIRES_NEW)
@Async("asyncImportExecutor")
public void startBeggin(Long id, String jwtToken) {

    try {
        . . .

    } catch (Exception e) {
        log.error("Error: " + e);

        utilsService.setFlag(id, 0L); // every type of error, revert flag to 0
    }

и метод utilService, вызываемый при перехвате, это

 public void setFlag(Long id, Long state) {

    /* recover data from repository */
    Processo processo = getRepo().getOne(id);
    processo.setAvanzamento(state);
    getRepo().saveAndFlush(processo);
}

этот метод (setFlag) вызывается один раз, передавая 1L перед вызовом асинхронного метода

getService().setFlag(id, (long) 1);

и в конце всех операций в методе асинхронности, передающих ноль

getService().setFlag(id, (long) 0);

, но, если метод асинхронности завершается с ошибкой из-за некоторых проблем, вызов в ветви перехвата завершается ошибкой, поскольку

org.springframework.orm.jpa.JpaSystemException: Transaction was marked for rollback only; cannot commit; nested exception is org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit

и флаг остается равным 1.

Итак, я надеюсь, что я все понял, но ... как я могу убедиться, что при любом исключении, которое происходит между операциями внутри асинхронного метода ( startBeggin) после отката этих операций установить это значение для этого объекта?

Как я могу установить (или обновить) поле для объекта, для отката транзакции (сбой)?

Объект бес действие транзакционного метода такое же (восстанавливается по идентификатору), но все операции roolbacked не связаны с этим флагом, который я хочу установить в любом случае.

Заранее спасибо всем, кто может дать мне решение / идея.

1 Ответ

1 голос
/ 29 марта 2020

Подход очень зависит от того, чего вы хотите достичь sh здесь. Но попытка дать простой ответ:

Транзакция была помечена только для отката

означает, что все изменения, внесенные в ресурсы базы данных, будут отменены (не сохранены) в конце транзакции -> в вашем случае в конце вашего startBeggin метода.

Таким образом, любые ресурсы базы данных, измененные в utilsService.setFlag, также не будут сохраняться -> выполнить текущую транзакцию уже помечен для отката.


Чтобы избежать этого, вам потребуется новая транзакция @Transactional(propagation = Propagation.REQUIRES_NEW) на utilsService.setFlag, которая будет изолирована от транзакция, созданная в методе startBeggin .

Вы также должны помнить, когда работает @Transactional:

https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html#transaction -declarative-annotations

...