← Назад к вопросам

К какой категории сущности относится Primary Key

2.0 Middle🔥 191 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

К какой категории сущности относится Primary Key

Primary Key (первичный ключ) относится к категории ИДЕНТИФИКАТОРОВ сущности. Это ключевая характеристика, которая уникально определяет каждую запись в таблице.

Классификация атрибутов сущности

Все атрибуты сущности в базе данных можно разделить на несколько категорий:

┌─────────────────────────────────────────────────────────┐
│          АТРИБУТЫ СУЩНОСТИ                              │
├─────────────────────────────────────────────────────────┤
│ 1. ИДЕНТИФИКАТОРЫ (Identifiers)                         │
│    ├─ Primary Key (Первичный ключ)                      │
│    ├─ Composite Key (Составной ключ)                    │
│    └─ Surrogate Key (Суррогатный ключ)                  │
├─────────────────────────────────────────────────────────┤
│ 2. ДЕСКРИПТОРЫ (Descriptors) — описывают сущность       │
│    ├─ Обычные атрибуты (name, email, etc)              │
│    └─ Производные атрибуты (calculated age)             │
├─────────────────────────────────────────────────────────┤
│ 3. ССЫЛКИ (References) — внешние ключи                  │
│    └─ Foreign Key (Внешний ключ)                        │
├─────────────────────────────────────────────────────────┤
│ 4. СЛУЖЕБНЫЕ (Service) — для синхронизации              │
│    ├─ created_at (timestamp)                            │
│    ├─ updated_at (timestamp)                            │
│    └─ version (for optimistic locking)                  │
└─────────────────────────────────────────────────────────┘

Primary Key как идентификатор

Primary Key — это уникальный идентификатор, обладающий свойствами:

// Пример: таблица User
@Entity
@Table(name = "users")
public class User {
    
    @Id  // ← Primary Key
    @GeneratedValue(strategy = GenerationType.UUID)
    private UUID id; // Идентификатор
    
    // Дескрипторы (описывающие сущность)
    @Column(nullable = false)
    private String email;
    
    private String name;
    private int age;
    
    // Внешний ключ (ссылка на другую сущность)
    @ManyToOne
    @JoinColumn(name = "company_id")
    private Company company;
    
    // Служебные поля
    @Column(updatable = false)
    private LocalDateTime createdAt;
    
    private LocalDateTime updatedAt;
}

Характеристики Primary Key

1. Уникальность (Uniqueness)

  • Каждое значение первичного ключа должно быть уникальным
  • Не может быть двух записей с одинаковым PK
CREATE TABLE users (
    id UUID PRIMARY KEY,    -- Уникальный
    email VARCHAR(255),     -- Может быть не уникальным
    name VARCHAR(255)
);

-- Попытка вставить дублирующийся id приведёт к ошибке
INSERT INTO users VALUES (123e4567-e89b-12d3-a456-426614174000, alice@example.com);
INSERT INTO users VALUES (123e4567-e89b-12d3-a456-426614174000, bob@example.com);
-- ERROR: duplicate key value violates unique constraint

2. Невозможность быть NULL (NOT NULL)

  • Primary Key не может быть пустым
  • Это гарантирует существование идентификатора
INSERT INTO users VALUES (NULL, alice@example.com, Alice);
-- ERROR: null value in column "id" violates not-null constraint

3. Неизменяемость (Immutability)

  • Первичный ключ должен быть неизменяемым
  • Нельзя менять идентификатор существующей записи
User user = userRepository.findById(userId).orElseThrow();
user.setId(newId); // ❌ Плохая практика!
// Это нарушит логику приложения

user.setName("New Name"); // ✅ Хорошо
user.setEmail("new@example.com"); // ✅ Хорошо

Типы Primary Keys

1. Simple (Простой) Primary Key

@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; // Один атрибут как PK
    
    private String name;
    private BigDecimal price;
}

2. Composite (Составной) Primary Key

@Embeddable
public class OrderItemId {
    @Column(name = "order_id")
    private Long orderId;
    
    @Column(name = "product_id")
    private Long productId;
    
    // Equals и hashCode обязательны
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof OrderItemId)) 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; // Составной PK
    
    private int quantity;
    private BigDecimal price;
}

3. Natural Primary Key (использует бизнес-данные)

@Entity
public class Country {
    @Id
    @Column(length = 2)
    private String countryCode; // ISO-2 код
    
    private String name;
    
    // Пример: countryCode="US", "RU", "CN"
}

4. Surrogate Primary Key (искусственный, технический)

@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private UUID id; // Суррогатный ключ
    
    private String isbn;  // Natural key (может быть unique)
    private String title;
}

Primary Key vs Unique Key

@Entity
public class User {
    @Id
    private UUID id; // PRIMARY KEY
    
    @Column(unique = true, nullable = false)
    private String email; // UNIQUE KEY
    
    @Column(unique = true)
    private String phoneNumber; // UNIQUE KEY (может быть NULL)
}
-- В SQL эквивалент
CREATE TABLE users (
    id UUID PRIMARY KEY,           -- Primary Key
    email VARCHAR(255) NOT NULL UNIQUE,  -- Unique Key
    phone VARCHAR(20) UNIQUE       -- Может быть NULL
);

Отличия:

  • PRIMARY KEY: ровно один на таблицу, NOT NULL обязателен
  • UNIQUE KEY: может быть несколько, может содержать NULL

Primary Key в отношениях

@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; // Primary Key
    
    @ManyToOne
    @JoinColumn(name = "user_id", nullable = false)
    private User user; // Foreign Key (ссылка на Primary Key)
    
    private LocalDateTime orderDate;
}
-- Связь через Primary Key
CREATE TABLE orders (
    id BIGSERIAL PRIMARY KEY,
    user_id UUID NOT NULL REFERENCES users(id),
    order_date TIMESTAMP
);

Best Practices

// ✅ ХОРОШО
@Entity
public class GoodEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private UUID id;  // Surrogate key — лучше всего
    
    @Column(unique = true)
    private String uniqueBusinessKey; // Для natural lookups
}

// ❌ ПЛОХО
@Entity
public class BadEntity {
    @Id
    private String email;  // Не нужно менять, может быть NULL (нарушение)
    
    @Id
    @Column(name = "user_id")
    private Long userId;  // Несколько @Id?
}

Производительность Primary Key

// Индексирование
// Primary Key автоматически индексируется
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; // Автоматический индекс
    
    @Column(unique = true) // Также индексируется
    private String email;
}

// Быстрый поиск по PK
User user = userRepository.findById(123L); // O(log n)

// Поиск по другому полю может быть медленнее без индекса
User user = userRepository.findByEmail("alice@example.com"); // Нужен свой индекс

Заключение

Primary Key — это идентификатор сущности, который:

  • Уникально определяет каждую запись
  • Не может быть NULL
  • Должен быть неизменяемым
  • Автоматически индексируется для быстрого поиска
  • Используется для связей между таблицами

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

К какой категории сущности относится Primary Key | PrepBro