Какие ограничения (constraints) бывают в PostgreSQL
Что проверяют
Понимаете ли вы, какие гарантии даёт сама база, и отличаете ли их от валидации в Java-коде. Следом обычно спрашивают, как ограничения отражаются в JPA-сущностях и какое исключение прилетит в Spring при нарушении.
Как отвечать
Назовите шесть видов:
- NOT NULL: запрет пустого значения;
- CHECK: условие на значения одной строки, например
CHECK (age >= 18). Подзапросы и ссылки на другие таблицы не допускаются; - UNIQUE: запрет дублей в колонке или наборе колонок, под капотом создаётся уникальный B-tree индекс. Несколько
NULLпо умолчанию не конфликтуют; - PRIMARY KEY: UNIQUE плюс NOT NULL, один на таблицу. Для суррогатного ключа сейчас берут
GENERATED ALWAYS AS IDENTITY, а не устаревшийSERIAL; - FOREIGN KEY: ссылочная целостность и поведение при удалении родителя (
CASCADE,SET NULL,RESTRICT). Индекс на ссылающейся колонке нужно создавать самим; - EXCLUDE: запрет конфликтующих строк по произвольным операторам, например пересекающихся периодов
period WITH &&.
Затем свяжите с Java. Аннотации @Column(nullable = false, unique = true), @Table(uniqueConstraints = ...) и @JoinColumn влияют только на DDL, который Hibernate генерирует при ddl-auto. В рабочем проекте схему ведут миграциями Flyway или Liquibase, и ограничения описываются там. @NotNull из Bean Validation это проверка в приложении, база о ней не знает.
При нарушении драйвер отдаёт PSQLException с SQLState (23505 уникальность, 23503 внешний ключ), Hibernate заворачивает её в ConstraintViolationException, а Spring переводит в DataIntegrityViolationException. Её и ловят, чтобы вернуть 409 вместо 500.
Где спотыкаются
Путают @NotNull и nullable = false, считая, что аннотация на поле заменяет ограничение в базе.
Проверяют уникальность через existsByEmail() перед save(). Два параллельных запроса пройдут проверку одновременно, и спасёт только UNIQUE.
Удивляются, что исключение вылетает не на save(), а позже, при flush или коммите транзакции: Hibernate откладывает INSERT до сброса контекста. Исключение составляет стратегия IDENTITY, там вставка идёт сразу, чтобы получить ключ.