Spring @Transactional правила наследования - PullRequest
15 голосов
/ 29 марта 2012

У меня есть набор @Service bean-компонентов, которые наследуют основные функции от абстрактного класса. Я пометил каждую из конкретных услуг подкласса @Service и @Transactional. Абстрактный суперкласс содержит метод общедоступной точки входа для каждой из этих служб. Другими словами, у меня есть нечто похожее на следующее:

abstract class AbstractService {

    public void process() {
        // Do common initialisation code here
        processSpecific();
        // Do common completion code here
    }

    abstract protected void processSpecific();
}


@Service @Transactional
public class FirstSpecificService extends AbstractService {
    protected void processSpecific() {
        // Do specific processing code here
    }
}


@Service @Transactional
public class SecondSpecificService extends AbstractService {
    protected void processSpecific() {
        // Do different specific processing code here
    }
}

Конкретный код в каждой конкретной службе подкласса выполняет несколько вызовов на уровне DAO для внесения изменений в базу данных, в которой REQUIRED имеет тип распространения транзакции.

Теперь со службами, определенными выше, я обнаружил, что в каком-либо коде этих конкретных служб подклассов не было текущей транзакции, и каждый вызов уровня DAO создавал новую транзакцию, делал изменения, фиксировал транзакция и возврат.

Однако, если я аннотирую абстрактный суперкласс с @Transactional, тогда транзакция будет создана правильно, и все вспомогательные вызовы уровня DAO участвуют в текущей транзакции.

Итак, мой вопрос: каковы правила наследования поведения @Transactional? Почему Spring не использует @Transactional на конкретных службах подкласса, которые он фактически создает? Нужно ли @Transactional быть в суперклассе в этом случае, потому что именно в этом случае используется публичный метод точки входа?

Ответы [ 2 ]

12 голосов
/ 29 марта 2012

Из документации по весенней транзакции,

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

Даже если у вас есть @Transactional в вашей конкретной реализации и вы вызываете метод процесса, который фактически является транзакционным по вашей аннотации, но метод процесса, вызывающий processSpecific для вашего подкласса, не является транзакционным из-за этого внутреннего вызова.

Загляни в ткачество.

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

Читали ли вы часть о распространении транзакции и о том, как ее можно настроить с помощью @ Transactional ?

Другая область интереса заключается в том, что Spring рекомендует аннотировать конкретные классы (в отличие от аннотирования интерфейсов).

...