Зачем нужен первичный ключ?
JavaSQLбазы данныхпервичный ключ
Что проверяют
Понимаете ли вы, что первичный ключ это ограничение целостности, а не просто колонка id, и как он связан с JPA. Следом часто спрашивают, какой генератор ключа выбрать в Hibernate и почему UUID бывает проблемой.
Как отвечать
Основа:
- что гарантирует: уникальность и
NOT NULLодновременно. В таблице он один, но может быть составным; - зачем: однозначно адресовать строку, на него ссылаются внешние ключи, по нему ORM отличает одну сущность от другой;
- индекс: база создаёт под ним уникальный индекс автоматически. В MySQL InnoDB строки физически упорядочены по первичному ключу (кластерный индекс), а в PostgreSQL таблица остаётся кучей, и ключ это обычный уникальный B-tree;
- естественный или суррогатный: email или ИНН кажутся удобными, но меняются. Обычно берут суррогатный
bigintили UUID, а естественный ключ защищают ограничениемUNIQUE.
Дальше Java-часть. В JPA сущность без @Id не существует. Стратегии @GeneratedValue:
IDENTITY: автоинкремент базы. Hibernate узнаёт id только после вставки и поэтому не может группироватьINSERTв JDBC-батчи;SEQUENCE: id берётся из последовательности заранее, батчи работают, аallocationSize(по умолчанию 50) уменьшает число обращений к ней;UUID: удобен для генерации без базы, но случайный UUIDv4 разбрасывает вставки по всему индексу. Упорядоченный по времени UUIDv7 эту проблему снимает, в PostgreSQL 18 для него есть встроенная функцияuuidv7().
Где спотыкаются
Ставят знак равенства между первичным ключом и уникальным индексом. UNIQUE допускает NULL, и таких ограничений на таблице может быть сколько угодно.
Строят hashCode() сущности на сгенерированном id. До persist() он null, после меняется, и объект теряется в HashSet.
Берут IDENTITY для таблицы с массовой вставкой и не понимают, почему hibernate.jdbc.batch_size не даёт эффекта.