본문 바로가기

STUDY/Java

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을 구현해야 함
  • equalshashCode를 구현해야 함
@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이 발생한다.


결론: 복합 키를 사용하고 싶지 않다^^..