Ответ
Да, PRIMARY KEY может быть составным (composite), то есть состоять из двух или более столбцов таблицы. Уникальность записи в таком случае обеспечивается комбинацией значений этих столбцов.
Пример создания в SQL:
CREATE TABLE OrderItems (
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT,
PRIMARY KEY (order_id, product_id) -- Составной первичный ключ
);
Особенности составного PRIMARY KEY:
- Уникальность: Комбинация
(order_id, product_id)должна быть уникальна. - NOT NULL: Все столбцы, входящие в ключ, неявно получают ограничение
NOT NULL. - Индекс: Создается уникальный индекс по всем столбцам ключа, что ускоряет поиск и операции
JOIN.
Реализация в JPA/Hibernate:
-
С помощью
@IdClass:@Entity @IdClass(OrderItemId.class) public class OrderItem { @Id private Long orderId; @Id private Long productId; private Integer quantity; } public class OrderItemId implements Serializable { private Long orderId; private Long productId; // Обязательно переопределить equals() и hashCode() } -
С помощью
@EmbeddedId(часто предпочтительнее):@Entity public class OrderItem { @EmbeddedId private OrderItemId id; private Integer quantity; } @Embeddable public class OrderItemId implements Serializable { private Long orderId; private Long productId; // equals() и hashCode() }
Ответ 18+ 🔞
Да ты посмотри, какой народ безмозглый, блядь! Сидят, думают, что первичный ключ — это обязательно один столбик, как будто у них в голове хуй с винтом. А он, сука, может быть составным, понимаешь? То есть из двух, трёх, овердохуища столбцов сразу! Уникальность тогда проверяется по всей этой, блядь, сборной солянке.
Вот смотри, как в SQL это выглядит, чтоб ты не бздел:
CREATE TABLE OrderItems (
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT,
PRIMARY KEY (order_id, product_id) -- Вот он, красавец, составной!
);
А теперь слушай сюда, какие подводные ебучки тут есть:
- Уникальность, блядь: Теперь пара
(order_id, product_id)должна быть одна на весь белый свет. Два одинаковых заказа на один и тот же продукт? Да похуй, не прокатит! - NOT NULL: Все столбцы в ключе автоматом становятся обязательными. Хочешь
NULLсунуть? Иди нахуй, не выйдет. - Индекс: Под эту комбинацию создаётся уникальный индекс, так что поиск и джойны летают, как угорелые.
А в JPA/Hibernate, ёпта, вообще два способа, чтоб мозги не ебать:
-
Через
@IdClass— классика, для старых пердунов:@Entity @IdClass(OrderItemId.class) public class OrderItem { @Id private Long orderId; @Id private Long productId; private Integer quantity; } public class OrderItemId implements Serializable { private Long orderId; private Long productId; // Бля, не забудь equals() и hashCode(), а то всё пиздец накроется! } -
Через
@EmbeddedId— поумнее и почище будет:@Entity public class OrderItem { @EmbeddedId private OrderItemId id; // Вот он, весь ключ одним пакетом! private Integer quantity; } @Embeddable public class OrderItemId implements Serializable { private Long orderId; private Long productId; // И тут тоже equals() с hashCode(), куда без них, блядь? }
Вот и вся магия, сука. Не такой уж и страшный зверь, этот составной ключ. Главное — не выёбывайся и делай по правилам, а то Hibernate тебе такую Муму утопит, что мало не покажется!