💡 JPA에서 복합 기본키(Composite Primary Key) 매핑하기
좋아요(Favorite) 테이블은 다음과 같은 구조로 이루어짐:
- 유저(User)의 기본 키
- 산책 기록(Walk)의 기본 키
이 두 개의 컬럼을 조합하여 하나의 복합 기본 키로 사용해야 함.
이를 JPA에서는 다음의 2가지 방법으로 처리 가능
✅ 복합 기본키 매핑 방법 2가지
1. @IdClass 방식
관계형 데이터베이스(RDBMS)의 전통적인 방식에 가까움.
// 복합 키 클래스 정의
@NoArgsConstructor
@EqualsAndHashCode
public class FavoriteId implements Serializable {
private Long user;
private Long walk;
}
// Favorite Entity 정의
@Entity
@Getter
@IdClass(FavoriteId.class)
public class Favorite extends BaseEntity {
@Id
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
@Id
@ManyToOne
@JoinColumn(name = "walk_id")
private Walk walk;
}
📌 사용 예
Favorite favorite = new Favorite();
favorite.setUser(user);
favorite.setWalk(walk);
User user = favorite.getUser();
Walk walk = favorite.getWalk();
2. @EmbeddedId 방식
보다 객체지향적인 방식. 복합키를 하나의 객체로 구성하여 엔티티에 포함시킴.
// 복합 키 클래스 정의
@NoArgsConstructor
@EqualsAndHashCode
@Embeddable
public class FavoriteId implements Serializable {
private Long user;
private Long walk;
}
// Favorite Entity 정의
@Entity
@Getter
public class Favorite extends BaseEntity {
@EmbeddedId
private FavoriteId favoriteId;
@MapsId("user")
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
📌 사용 예
FavoriteId favoriteId = new FavoriteId(userId, walkId);
Favorite favorite = new Favorite();
favorite.setFavoriteId(favoriteId);
Long userId = favorite.getFavoriteId().getUser();
Long walkId = favorite.getFavoriteId().getWalk();
☑️ 두 방식의 공통점
조건설명
Serializable | 복합키 클래스는 Serializable 인터페이스 구현 필요 |
기본 생성자 | 반드시 public 기본 생성자 있어야 함 |
equals(), hashCode() | 필수 오버라이딩 |
접근 제어자 | 필드는 public 또는 접근 가능한 getter/setter 필요 |
🤔 어떤 방식이 더 적절할까?
상황추천 방식
엔티티 내부에서만 사용하는 단순한 구조 | @EmbeddedId |
복합 키가 재사용되거나 구조가 복잡 | @IdClass |
객체지향적으로 깔끔하게 묶고 싶다면 → @EmbeddedId
DB 설계에 더 밀접하고 복잡한 관계를 표현한다면 → @IdClass
💡 팁
팁 1: @EmbeddedId 사용할 때는 @MapsId를 반드시 써서 복합키 필드와 실제 관계를 연결해야 합니다.
팁 2: @IdClass를 사용할 경우, 복합 키 클래스에서 필드명과 타입은 엔티티의 @Id 필드와 정확히 일치해야 함.
팁 3: 복합 키 클래스는 JPA에서 엔티티로 간주하지 않으므로, @Entity는 쓰지 않아야 합니다.