Аннотация @Transactional в Spring управляет транзакциями на уровне базы данных, обеспечивая атомарность операций с БД внутри одного сервиса.
Вопрос 8. Есть сервис ExampleService (см. рис).
Аннотация @Transactional в Spring управляет транзакциями на уровне базы данных, обеспечивая атомарность операций с БД внутри одного сервиса.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Вопрос 8. Есть сервис ExampleService (см. рис).
Метод OrderDao::delete удаляет заказ из БД сервиса. Метод DeliveryService::cancelDelivery синхронно обращается к другому сервису по http и в случае ошибки выбрасывает RuntimeException.
Возможно ли использование аннотации @Transactional над методом ExampleService::handle для обеспечения консистентности?
@Component @RequiredArgsConstructor public class ExampleService {
private final OrderDao orderDao;
private final DeliveryService deliveryService;
@Transactional
public void handle(long orderId) {
orderDao.delete(orderId);
deliveryService.cancelDelivery(orderId);
}
}
- Да, в случае ошибки изменения в БД откатятся
- Нет, пользователь не узнает, что заказ не был удален
- Нет, могут возникнуть утечки памяти в слое http клиента
- Нет, могут возникнуть таймауты в слое обращения к БД
Ответ
Аннотация @Transactional в Spring управляет транзакциями на уровне базы данных, обеспечивая атомарность операций с БД внутри одного сервиса.
В этом случае метод ExampleService::handle вызывает orderDao.delete — операцию с БД, и deliveryService.cancelDelivery — HTTP вызов к другому сервису.
Проблема в том, что транзакция @Transactional не распространяется на внешние HTTP вызовы. Если deliveryService.cancelDelivery выбросит RuntimeException, то транзакция с удалением заказа в БД откатится, и заказ не удалится.
Однако, если deliveryService.cancelDelivery завершится с ошибкой после удаления заказа, то транзакция откатится, и пользователь узнает, что заказ не был удален.
Таким образом, ответ:
- Да, в случае ошибки изменения в БД откатятся
Но важно понимать, что @Transactional не обеспечивает распределённую транзакционность между сервисами. Для консистентности между сервисами нужны другие паттерны (например, саги, компенсационные транзакции).
Другие варианты ответов не соответствуют сути:
- Пользователь узнает об ошибке, так как RuntimeException выбрасывается
- Утечки памяти и таймауты не связаны напрямую с @Transactional
Итог: использование @Transactional здесь возможно и откатит изменения в БД при ошибке, но не гарантирует консистентность между сервисами.