Правила наследования весны @Transactional

У меня есть набор компонентов @Service которые наследуют функциональность ядра от абстрактного класса. Я пометил каждую из конкретных служб @Service с помощью @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 ли @Transactional быть в суперклассе в этом случае, потому что это то, где метод публичной точки входа?

Ответ 1

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

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

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

Посмотрите на Ткачество.