Назад к вопросам
Junior
162
questionbank

Что такое составной (composite) ключ?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Составной (или композитный) ключ в базе данных — это первичный ключ, состоящий из двух или более столбцов таблицы. Уникальность записи определяется комбинацией значений всех столбцов, входящих в составной ключ.

В Java-приложениях, использующих JPA, составной ключ обычно реализуется одним из двух способов:

  1. Используя @Embeddable и @EmbeddedId:

    Создается отдельный класс, помеченный аннотацией @Embeddable, который инкапсулирует поля, составляющие составной ключ. В сущности этот класс внедряется с помощью аннотации @EmbeddedId. Класс, представляющий составной ключ, должен реализовывать Serializable и переопределять методы equals() и hashCode().

    // Класс составного ключа
    @Embeddable
    public class OrderItemId implements Serializable {
    
        private Long orderId;
        private Long productId;
    
        // Конструкторы, геттеры, сеттеры
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            OrderItemId that = (OrderItemId) o;
            return Objects.equals(orderId, that.orderId) &&
                   Objects.equals(productId, that.productId);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(orderId, productId);
        }
    }
    
    // Сущность с составным ключом
    @Entity
    public class OrderItem {
    
        @EmbeddedId
        private OrderItemId id;
    
        private int quantity;
    
        // Конструкторы, геттеры, сеттеры
    }
    
  2. Используя @IdClass:

    Создается отдельный класс, представляющий составной ключ (также реализующий Serializable и переопределяющий equals() и hashCode()), и в сущности указывается имя этого класса с помощью аннотации @IdClass. Поля, входящие в составной ключ, объявляются прямо в сущности и помечаются аннотацией @Id. Имена полей в сущности и классе ключа должны совпадать.

    // Класс составного ключа
    public class OrderItemId implements Serializable {
    
        private Long orderId;
        private Long productId;
    
        // Конструкторы, геттеры, сеттеры
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            OrderItemId that = (OrderItemId) o;
            return Objects.equals(orderId, that.orderId) &&
                   Objects.equals(productId, that.productId);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(orderId, productId);
        }
    }
    
    // Сущность с составным ключом
    @Entity
    @IdClass(OrderItemId.class)
    public class OrderItem {
    
        @Id
        private Long orderId;
    
        @Id
        private Long productId;
    
        private int quantity;
    
        // Конструкторы, геттеры, сеттеры
    }