Ответ
Поведение зависит от того, помечен ли метод b аннотацией @Transactional и какое у него распространение (propagation).
Сценарии:
-
Метод b НЕ помечен @Transactional:
- Код метода
bвыполняется в той же транзакции, что и методa. Аннотации нет — новых транзакций не создаётся.
- Код метода
-
Метод b помечен @Transactional с propagation по умолчанию (REQUIRED):
- Если вызов идёт через прокси (например, из другого бина), то Spring присоединит метод
bк существующей транзакции методаa. - Если вызов идёт внутри одного класса (как в вопросе), аннотация
@Transactionalнаbигнорируется из-за ограничений proxy-based AOP. Работает как сценарий 1.
- Если вызов идёт через прокси (например, из другого бина), то Spring присоединит метод
-
Метод b помечен @Transactional(propagation = Propagation.REQUIRES_NEW):
- При вызове через прокси Spring приостановит текущую транзакцию метода
a, создаст и запустит новую независимую транзакцию дляb, а после её завершения возобновит транзакциюa. - При внутреннем вызове внутри класса — снова не сработает (как в п.2).
- При вызове через прокси Spring приостановит текущую транзакцию метода
Практический пример с разными propagation:
@Service
public class TransactionService {
@Transactional
public void methodA() {
// Транзакция Tx-A
repo.save(entityA);
try {
// Вызов через прокси другого бина:
otherService.methodB_REQUIRES_NEW(); // Будет Tx-B
} catch (Exception e) {
// Откат Tx-B НЕ повлияет на Tx-A
}
// Продолжение Tx-A
}
}
@Service
class OtherService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB_REQUIRES_NEW() {
// Новая, независимая транзакция Tx-B
// Её откат не затронет Tx-A
}
}
Итог: Чтобы управление транзакциями работало предсказуемо, вызовы должны идти через прокси (между разными бинами).