JPA | 복합 키 (Composite Key) 사용하기 (@IdClass)
JPA에서 식별자(@Id
)를 둘 이상 사용하려면 별도의 식별자 클래스를 만들어야 한다.
JPA는 복합 키를 지원하기 위해 @IdClass
와 @EmbeddedId
두 가지 방법을 제공하는데@IdClass
는 관계형 데이터베이스에 가까운 방법이고 @EmbeddedId
는 좀 더 객체지향에 가까운 방법이다.
출처: 김영한 저 자바 ORM 표준 JPA 프로그래밍 256p.
@IdClass
엔티티 클래스에서 @IdClass
애노테이션을 사용한다.USER
라는 테이블의 기본키를 id와 regDate(가입일)을 조합하여 사용한다고 가정할 때, 엔티티 클래스를 아래와 같이 작성한다.@Id
애노테이션을 가진 필드가 두 개 이상. 즉 복합키를 사용해야 하고, @IdClass()
애노테이션에 복합 키를 매핑하기 위한 클래스를 지정한다.
@IdClass(UserId.class)
@Entity
public class User {
@Id
@Column(name = "USER_ID")
private String id;
@Id
@Column(name = "REG_DATE")
private LocalDateTime regDate;
// 생략
}
복합 키를 매핑하기 위한 클래스를 작성해준다. 복합 키 클래스를 작성할 때는 몇 가지 주의해야 할 사항들이 있다.
public
클래스일 것- 기본 생성자 필수
- 엔티티 클래스에서 작성한 필드 명과 동일하게 작성할 것 (컬럼명이 아님에 주의)
Serializable
을 구현해야 함equals
와hashCode
를 구현해야 함
@AllArgsConstructor
@NoArgsConstructor
public class UserId implements Serializable {
private String id;
private LocalDateTime regDate;
// equals & hashCode 부분 생략
}
그리고 복합 키를 사용하면 @GeneratedValue
를 사용할 수 없다. 무조건 식별자 값을 입력해주어야 한다.
@GeneratedValue
없이@Id
애노테이션만 사용할 경우에는 애플리케이션에서 직접 식별자 값을 설정해주어야 한다.
위의 상황처럼 복합 키 중 하나가 TIMESTAMP타입 컬럼이고, DDL의 default value가 CURRENT_TIMESTAMP로 지정되어 있어도 직!접! 입력해야 한다. (insertable = false도 안 통 한 다)
INSERT문을 만들 때 무조건 필요하기 때문에 생략할 경우 NullPointException이 발생한다.
결론: 복합 키를 사용하고 싶지 않다^^..