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

В чем разница между определением @Transactional по методу класса vs

Case1

@Transactional
public class UserServiceImpl implements UserService {

    ...................
    public void method1(){
        try{
            method2();
        }catch(Exception e){

        }
    }
    public void method2(){

    }
}

Вариант 2

public class UserServiceImpl implements UserService {

    ...................
    public void method1(){
        try{
            method2();
        }catch(Exception e){

        }
    }
    @Transactional
    public void method2(){

    }
}

В случае 1, если возникает какое-либо исключение, он откатывается, но в случае 2 он не работает. Есть ли проблемы с производительностью, если я следую case1?

4b9b3361

Ответ 1

В случае 1 @Transactional применяется к каждому отдельному методу. В случае 2 @Transactional применяется только к method2(), а не к method1()

Случай 1: - Вызов метода method1() → транзакция запущена. Когда method1() вызывает method2(), новая транзакция не запускается, потому что она уже есть

Случай 2: - Вызов метода method1() → транзакция не запущена. Когда method1() вызывает method2(), NO новая транзакция не запускается. Это связано с тем, что @Transactional не работает при вызове метода из одного и того же класса. Это сработало бы, если бы вы вызывали method2() из другого класса.

Из весеннего справочного руководства:

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

Ответ 2

@Transactional для класса применяется к каждому методу в сервисе. Это ярлык. Как правило, вы можете установить @Transactional(readOnly = true) для класса обслуживания, если вы знаете, что все методы будут обращаться к уровню хранилища. Затем вы можете переопределить поведение с помощью @Transactional для методов, выполняющих изменения в вашей модели. Проблемы с производительностью между 1) и 2) не известны.

Ответ 3

Цитата из здесь

Рекомендация команды Spring заключается в том, что вы только аннотируете конкретные классы с аннотацией @Transactional, в отличие от аннотирующих интерфейсов.

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

Ответ 4

Предположим, что у вас есть следующий класс:

@Transactional(readOnly = true)
public class DefaultFooService implements FooService {

  public Foo getFoo(String fooName) {
    // do something
  }

  // these settings have precedence for this method
  @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
  public void updateFoo(Foo foo) {
    // do something
  }
}

Аннотация @Transactional на уровне класса будет применяться ко всем методам класса.

Однако, когда метод аннотируется с помощью @Transactional (например, updateFoo(Foo foo)), это будет иметь приоритет над параметрами транзакции, определенными на уровне класса.

Дополнительная информация: