복합 키(Composite Key)란?
- 하나의 테이블이 2개 이상의 컬럼을 조합해 PK(기본 키)를 구성하는 경우
- 흔히 다대다(N:M) 관계를 풀어내는 조인 테이블에서 자주 사용
예시 테이블 구조
CREATE TABLE order_items (
order_id BIGINT,
product_id BIGINT,
quantity INT,
PRIMARY KEY (order_id, product_id) # order_id + product_id 가 복합 PK
);
- 하나의 주문(Order)에는 여러 상품(Product)이 포함될 수 있음
- 하나의 상품은 여러 주문에 포함될 수 있음
- 이 경우 OrderItem 테이블은 order_id 와 product_id 를 묶어서 복합 키로 사용
JPA에서 복합 키를 정의하는 방법
대표적으로 @IdClass 방식과 @EmbeddedId 방식이 있다.
@IdClass 방식
- 복합 키를 외부 식별자 클래스로 정의하고, 엔티티 내부에서 각 키 필드를 개별적으로 선언하는 방식
- 이 방식은 구조가 단순한 조인 테이블에 특히 유용함. 예를 들어 학생(Student)과 수업(Course)의 다대다 관계를 풀어내는 중간 테이블(StudentCourse)처럼, 복합 키만 정의하면 되는 테이블에서는 빠르고 간단하게 구현할 수 있음
- 식별자 클래스와 엔티티 클래스 양쪽에 동일한 필드를 선언해야 함 → 코드 중복
- 레거시 시스템을 다루거나 기존 데이터베이스 모델이 POJO 스타일로 구성된 경우
- 필드의 개별 접근이 자주 필요하거나, 별도의 연관관계 없이 식별자만으로 조회하는 경우
식별자 클래스 생성
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import jakarta.persistence.Embeddable;
import java.io.Serializable;
@Getter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
// @Embeddable 안 씀 !
public class OrderItemId implements Serializable {
private Long orderId;
private Long productId;
}
Entity 클래스
import jakarta.persistence.*;
@Entity
@IdClass(OrderItemId.class)
public class OrderItem {
@Id
private Long orderId;
@Id
private Long productId;
private int quantity;
/*
연관관계 매핑(예: Order, Product) 추가 시
@ManyToOne
@JoinColumn(name = "order_id", insertable = false, updatable = false)
private Order order;
@ManyToOne
@JoinColumn(name = "product_id", insertable = false, updatable = false)
private Product product;
*/
// 기본 생성자, getter/setter 생략
}
@EmbeddedId 방식
- 복합 키를 하나의 값 객체로 만들어, 해당 객체를 엔티티의 식별자로 사용하는 방식
- 코드 중복이 없고 구조적으로 더 깔끔함
- 객체지향적인 설계를 선호하는 경우
- 엔티티와 연관관계 매핑이 필요한 경우 (@EmbeddedId + @MapsId)
- 복합 키 자체가 하나의 도메인 객체로 의미가 있을 경우 적합
복합 키 클래스 정의
import jakarta.persistence.Embeddable;
@Getter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Embeddable // @EmbeddedId 방식일 때는 꼭 필요!
public class OrderItemId implements Serializable {
private Long orderId;
private Long productId;
}
Entity 클래스
import jakarta.persistence.*;
@Entity
public class OrderItem {
@EmbeddedId
private OrderItemId id;
private int quantity;
/*
연관관계 매핑(예: Order, Product) 추가 시
@ManyToOne
@MapsId("orderId")
@JoinColumn(name = "order_id")
private Order order;
@ManyToOne
@MapsId("productId")
@JoinColumn(name = "product_id")
private Product product;
*/
// 기본 생성자, getter/setter 생략
}'📚 Study' 카테고리의 다른 글
| 인증과 인가, 그리고 JWT (1) | 2025.08.05 |
|---|
