[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-spring-kakie-podvodnye-kamni-est-u-transactional":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":15,"progress":16,"seo":17},622,"kakie-podvodnye-kamni-est-u-transactional",14,"spring","Spring","🌱","Какие подводные камни есть у @Transactional?","Это один из самых популярных вопросов на собеседованиях. Подводные камни `@Transactional` -- проверка глубины понимания Spring.\n\n### 1. Self-invocation (вызов из того же класса)\n\n`@Transactional` работает через прокси. Вызов метода внутри того же класса обходит прокси:\n\n```java\n@Service\npublic class UserService {\n    @Transactional\n    public void updateUser(User user) {\n        userRepository.save(user);\n    }\n\n    public void processUser(Long userId) {\n        User user = userRepository.findById(userId).orElseThrow();\n        this.updateUser(user); \u002F\u002F @Transactional НЕ сработает!\n    }\n}\n```\n\nРешения: вынести в другой сервис или использовать self-injection (`@Autowired private UserService self;`).\n\n### 2. Checked exceptions не вызывают откат\n\n```java\n@Transactional \u002F\u002F НЕ откатится при IOException!\npublic void saveFile(MultipartFile file) throws IOException {\n    userRepository.save(user);\n    fileStorage.store(file); \u002F\u002F бросает IOException -- транзакция коммитится!\n}\n\n\u002F\u002F Правильно:\n@Transactional(rollbackFor = Exception.class)\npublic void saveFile(MultipartFile file) throws IOException { }\n```\n\n### 3. @Transactional на private методе не работает\n\nSpring AOP не может создать прокси для private-метода.\n\n### 4. Проглатывание исключения\n\n```java\n@Transactional\npublic void process() {\n    try {\n        riskyOperation();\n    } catch (Exception e) {\n        log.error(\"Error\", e);\n        \u002F\u002F исключение проглочено -- транзакция закоммитится,\n        \u002F\u002F хотя данные могут быть в некорректном состоянии\n    }\n}\n```\n\n### 5. Долгие операции внутри транзакции\n\n```java\n@Transactional\npublic void processOrder(Order order) {\n    orderRepository.save(order);\n    emailService.sendEmail(order); \u002F\u002F долгая операция -- блокирует соединение с БД!\n}\n```\n\nОтправку уведомлений нужно выносить за пределы транзакции или делать асинхронно.\n\n### 6. Не указан TransactionManager при нескольких DataSource\n\n```java\n@Transactional(\"secondaryTransactionManager\")\npublic void saveToSecondaryDb(Data data) { }\n```\n\n> **На собеседовании:** это вопрос для senior-уровня. Интервьюер ждёт минимум 3-4 подводных камня с примерами. Главные: self-invocation, checked exceptions, private-методы. Частая ошибка -- не знать про self-invocation или думать, что любое исключение откатит транзакцию.","","senior",[7],[],null,{"title":18,"description":19,"ogTitle":18,"ogDescription":20,"keywords":21,"schemaAnswer":19,"featuredSnippetReady":22},"Какие подводные камни есть у @Transactional? — Gymterview","Это один из самых популярных вопросов на собеседованиях. Подводные камни `@Transactional` -- проверка глубины понимания Spring.","Это один из самых популярных вопросов на собеседованиях. Подводные камни `@Transactional` -- проверка глубины понимания ",[7,13],true]