Хранимые процедуры, функции, триггеры
Хранимая процедура/функция — код, который живёт и выполняется прямо внутри базы данных, а не в Java-приложении.
CREATE FUNCTION get_user_age(user_id INT) RETURNS INT AS $$
DECLARE age INT;
BEGIN
SELECT EXTRACT(YEAR FROM AGE(birth_date)) INTO age FROM users WHERE id = user_id;
RETURN age;
END;
$$ LANGUAGE plpgsql;
SELECT get_user_age(1);
Триггер — функция, которая запускается автоматически при определённом событии (вставка, изменение, удаление строки):
CREATE TRIGGER update_timestamp
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION set_updated_at(); -- автоматически обновит поле updated_at
Копнуть глубже
Когда это уместно, а когда нет. Хранимые процедуры удобны для логики, которая обязана выполняться независимо от того, какое приложение пишет в базу (несколько сервисов на разных языках работают с одной БД). Но в современной разработке бизнес-логику чаще держат в коде приложения (Java/Spring), а не в базе — так проще тестировать, версионировать в Git, дебажить через привычные инструменты.
Триггеры особенно нужно использовать осторожно — они выполняются “невидимо” для разработчика, читающего код приложения: видишь UPDATE users, а на самом деле сработала ещё куча скрытой логики в триггере. Это усложняет понимание системы и отладку, если триггеров много и они не задокументированы.
Где это реально оправдано: аудит изменений (логирование кто/когда менял данные), поддержание целостности на уровне БД, когда несколько разных систем пишут в одну базу напрямую.
• почему бизнес-логику чаще держат в коде приложения, а не в БД (если дошёл до 2-го слоя).