Как обрабатывать транзакции Spring внутри сопрограмм? - PullRequest
0 голосов
/ 14 сентября 2018

Известно, что транзакции Spring привязаны к потокам: существуют локальные потоки, специфичные для текущей транзакции. И транзакции ничего не знают о сопрограммном контексте. Так что, если я хотел бы вызвать метод @Transactional из сопрограммы: это безопасно?

Представьте, что внутри компонента EJB JobProcessor есть метод, обрабатывающий список заданий. Каждое задание обрабатывается внутри async {}. И я хотел бы обновлять БД после каждой успешной или неудачной обработки, используя методы @Transactional bean JobService.

class JobProcessor {
    fun process(jobs: List<MyJob>) =
        jobs.map { job ->
            async {
                try {
                    ....//processing
                    jobService.success(job)
                } catch (t: Throwable) {
                    jobService.failure(job)
                }
        }
} 

class JobService {
    @Transactional
    fun success(job: MyJob) {...}

    @Transactional
    fun failure(job: MyJob) {...}
} 

1 Ответ

0 голосов
/ 15 сентября 2018

Во-первых, имейте в виду, что аннотирования методов bean с @Transactional будет недостаточно - убедитесь, что вы включили декларативную обработку транзакций, например, добавив @EnableTransactionManagement к классу @Configuration или используя <tx-annotation-driven /> в XML-конфигурации,

Относительно вашего вопроса: будет существовать транзакционный контекст при выполнении методов bean-компонентов Spring, помеченных @Transactional, когда они вызываются из bean-компонента Spring вне их содержащего класса!Декларативные транзакции в Spring полагаются на прокси-классы AOP, создаваемые для аннотированных классов @Transactional Spring.Во время выполнения, если bean-компонент Spring вызывает метод @Transactional для bean-компонента Spring, вызов будет перехвачен прокси-сервером AOP, который прозрачно порождает транзакцию, вызывает исходный метод bean-компонента Spring B и впоследствии фиксирует или откатывает эту транзакцию.

Помните: будут перехватываться только внешние вызовы методов, поступающие через прокси-сервер - любые вызовы самовывозов, как в вашем примере this.process (), вызывающий @Transactional методов this.success() или this.failure() не запустит транзакцию - даже если метод помечен @Transactional.

...