Не покрывайте метод в транзакции, который выполняется внутри транзакционного метода - PullRequest
1 голос
/ 20 февраля 2020

Я где-то задавал этот вопрос,

Предположим, у меня есть метод A, который выполняется в транзакции с использованием @transactional, если есть метод B, который вызывается из этого транзакционного метода, по умолчанию это также будет выполняться в той же транзакции.

Итак, вопрос в том, что делать, чтобы B не охватывалось транзакцией, как избежать транзакции для B.

Ответы [ 2 ]

1 голос
/ 26 февраля 2020

Исходя из комментария о том, что оба метода находятся в одном классе (собственный вызов), может работать следующий код.

 @Service
public class TestService {

    @Autowired // Self autowiring
    TestService service;

    @Transactional
    public void methodA() {
        service.methodB();
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void methodB() {
        //...
    }
}

Внешний вызов service.methodA() инициализирует транзакцию и сам вызов service.methodB() приведет к тому, что methodB() будет также частью той же транзакции, даже если она аннотирована, чтобы не участвовать в транзакции. Чтобы обойти это, мы автоматически подключаемся и в этом случае вызываем methodB(). Это приведет к выполнению конфигурации транзакции для methodB().

Ниже приведена причина для самостоятельного автоматического подключения, документация

В режиме прокси (который по умолчанию), только внешние вызовы методов, поступающие через прокси, перехватываются. Это означает, что самовывоз (по сути, метод в целевом объекте, вызывающий другой метод целевого объекта) не приводит к фактической транзакции во время выполнения, даже если вызванный метод помечен как @ Transactional.

Ссылка: Propagation.NOT_SUPPORTED

Выполнить без транзакций, приостановить текущую транзакцию, если она существует. Аналогично атрибуту транзакции EJB с тем же именем.

Пожалуйста, ознакомьтесь с разделом do c, указанным для ограничений этого поведения при распространении. Надеюсь, это поможет

1 голос
/ 20 февраля 2020

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

void myFunction() {
        Object result = myTransactionalClass.A();
        B(result);
}

Будьте осторожны, так как Вы задаете этот вопрос (вы не хотите, чтобы B () был транзакционным), упомянутый код наиболее точно сработает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...