Где должен я помещать @Transactional аннотацию: в интерфейсном определении или в классе с реализацией?

Вопрос из заголовка в коде:

@Transactional (readonly = true)
public interface FooService {
   void doSmth ();
}


public class FooServiceImpl implements FooService {
   ...
}

по сравнению с

public interface FooService {
   void doSmth ();
}

@Transactional (readonly = true)
public class FooServiceImpl implements FooService {
   ...
}
82
задан Roman 25 June 2010 в 17:41
поделиться

4 ответа

Из http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

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

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

(Курсив добавлен к первому предложению, другой ударение из оригинала.)

112
ответ дан 24 November 2019 в 09:16
поделиться

Вы можете поместить их в интерфейс, но имейте в виду, что в некоторых случаях транзакции могут не завершиться. См. Второй совет в разделе 10.5.6 документации Spring:

Spring рекомендует аннотировать только конкретные классы (и методы конкретных классов) с помощью аннотации @Transactional, а не аннотировать интерфейсы. Вы, конечно, можете разместить аннотацию @Transactional в интерфейсе (или методе интерфейса), но это работает только так, как вы ожидаете, если вы используете прокси на основе интерфейса. Тот факт, что аннотации Java не наследуются от интерфейсов, означает, что если вы используете прокси на основе классов (proxy-target-class = "true") или аспект на основе ткачества (mode = "aspectj"), тогда настройки транзакции не распознается инфраструктурой проксирования и переплетения, и объект не будет заключен в транзакционный прокси, что было бы определенно плохим.

По этой причине я бы рекомендовал включить их в реализацию.

Кроме того, для меня транзакции кажутся деталью реализации, поэтому они должны быть в классе реализации. Представьте, что у вас есть реализации оболочки для ведения журнала или тестирования (макеты), которые не обязательно должны быть транзакционными.

9
ответ дан 24 November 2019 в 09:16
поделиться

Spring Рекомендация заключается в том, что вы аннотируете конкретные реализации вместо интерфейса. Использование аннотации в интерфейсе не является неправильным, просто можно злоупотребить этой функцией и непреднамеренно обойти ваше объявление @Transaction.

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

На практике это выглядит примерно так:

public class MyClass implements MyInterface { 

    private int x;

    public void doSomethingNonTx() {}

    @Transactional
    public void toSomethingTx() {}

}
8
ответ дан 24 November 2019 в 09:16
поделиться

Ввести его в интерфейс - это нормально, пока все предполагаемые разработчики вашего IFC заботятся о данных TX (транзакции - это не проблемы, с которыми имеют дело только базы данных). Если метод не заботится о TX (но вам нужно поместить его туда для Hibernate или чего-то еще), поместите его в impl.

Кроме того, было бы лучше разместить @Transactional в методах интерфейса:

public interface FooService {
    @Transactional(readOnly = true)
    void doSmth();
}
0
ответ дан 24 November 2019 в 09:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: