Как работает @Transactional
Вопрос
Расскажите, как работает @Transactional в Spring, и назовите ситуации, когда он не срабатывает.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Прокси и TransactionInterceptor, PlatformTransactionManager
Соединение и EntityManager в ThreadLocal потока
Commit или rollback по исключениям: unchecked откат, checked коммит
Не работает: this-вызов, private, final, другой поток, new
Propagation и rollback-only
Короткие транзакции без внешних вызовов, AFTER_COMMIT события
Что могут спросить следом
- Чем REQUIRES_NEW отличается от NESTED?
- Где ставить @Transactional: в сервисе или репозитории?
Разбор
Бин с @Transactional оборачивается прокси. При вызове TransactionInterceptor через PlatformTransactionManager, для JPA это JpaTransactionManager, берёт соединение, выключает autocommit и привязывает соединение и EntityManager к потоку через ThreadLocal, оттуда их находят репозитории. После метода коммит, а если вылетел RuntimeException или Error, откат; checked-исключения по умолчанию коммитятся, это меняется rollbackFor. Не срабатывает, когда вызов не проходит через прокси: через this, на private или final методе, у объекта из new, в конструкторе. И транзакция не переходит в другой поток. Отдельная ловушка: внутренний REQUIRED-метод бросил исключение, внешний поймал, а при коммите UnexpectedRollbackException, потому что транзакция уже помечена rollback-only. Транзакции держу короткими, внешние вызовы и письма выношу после коммита через TransactionalEventListener или outbox.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.