Ответ
Перенос бизнес-логики из хранимых процедур (Stored Procedures) в код приложения продиктован принципами современной разработки:
| Недостаток хранимых процедур | Последствие | Решение в коде приложения |
|---|---|---|
| Сложность тестирования | Невозможность изолированного unit-тестирования, зависимость от конкретной БД для интеграционных тестов. | Логика покрывается модульными и интеграционными тестами с использованием in-memory БД или моков. |
| Нарушение инкапсуляции | Распределение логики между БД и приложением, усложнение понимания системы. | Четкое разделение: БД — хранение данных, приложение — бизнес-логика. |
| Вендорная привязка | Синтаксис и возможности специфичны для СУБД (Oracle PL/SQL, PostgreSQL PL/pgSQL), что блокирует миграцию. | Использование ORM (Hibernate) или SQL-мапперов (MyBatis) с диалектами позволяет легче менять БД. |
| Сложность CI/CD и контроля версий | Хранимые процедуры часто выпадают из стандартного цикла сборки и системы контроля версий (Git). | Код приложения полностью интегрирован в Git и pipeline сборки/деплоя. |
Пример: Вместо вызова процедуры CALL transfer_funds(acc_from, acc_to, sum); логика явно описывается в сервисе:
@Transactional
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
Account from = accountRepository.findById(fromId).orElseThrow();
Account to = accountRepository.findById(toId).orElseThrow();
// Вся бизнес-логика (проверки, расчеты) здесь
from.withdraw(amount);
to.deposit(amount);
accountRepository.saveAll(List.of(from, to));
auditService.logTransaction(fromId, toId, amount); // Аудирование тоже в коде
}
Хранимые процедуры остаются оправданы для сложных аналитических отчетов или критичных по производительности массовых операций с данными.