[자바 ORM 표쥰 JPA 프로그래밍] 14일차 - 복합키 엔티티
데이터베이스에서 PK를 2개 이상가진 테이블의 기본키를 보고는 복합키라고 부른다.
이를 JPA에서는 식별클래스를 사용하여 관리한다.
1. 식별클래스
PARENT 테이블 보면 PK를 2개 갖고있는데 이를 보고 복합키라고 부른다.
JPA 는 hashCode와 equals 를 사용하여 영속성 컨텍스트에서 식별자를 구분하게 되는데
PK가 하나만 있다면 문제는 없지만 2개이상 있는 복합키를 가진 엔티티의 경우 별도의 식별 클래스로 구분하게된다.
2. @IdClass
데이터베이스 관점으로 식별자 클래스를 생성하기 위해서는 @IdClass 어노테이션을 사용한다.
@Data
// implements Serializable 가 필수이다.
public class ParentId implements Serializable {
private Long id1;
private Long id2;
}
@IdClass(ParentId.class) // 식별자 클래스를 명시
@Data
@Entity
public class Parent {
@Id
@GeneratedValue
@Column(name = "PARENT_ID1")
private Long id1;
@Id
@GeneratedValue
@Column(name = "PARENT_ID2")
private Long id2;
private String name;
}
식별자용 클래스 ParentId 를 생성하고 implements Serializable 를 상속해야한다.
그리고 필드를 복합키를 가진 엔티티의 필드와 동일하게 맞춰서 생성해주어야한다.
복합키 엔티티는 클래스단에 @IdClass 어노테이션을 명시하여 VALUE에 식별 클래스를 등록하면 된다.
public static void login(EntityManager em){
// INSERT DATA
// Parent parent = new Parent();
// parent.setName("패런츠");
// em.persist(parent);
// SELECT DATA
// 식별자 인스턴스를 생성하여 PK로 사용
ParentId parentId = new ParentId();
parentId.setId1(1l);
parentId.setId2(2l);
final Parent findParent = em.find(Parent.class, parentId);
System.out.println("findParent = " + findParent.getName());
}
조회시에는 기존 방식에서 PK만 식별 클래스로 사용하면 된다.
3. @EmbeddedId
@IdClass 어노테이션이 데이터베이스 관점이였다면 @EmbeddedId 어노테이션을 객체지향적 관점으로 사용된다.
@Data
@Entity
public class Parent {
// 식별 클래스를 타입으로 하여 하나만 사용
@EmbeddedId
private ParentId parentId;
private String name;
}
@Data
@Embeddable // 식별클래스로 사용하겠다는 어노테이션
public class ParentId implements Serializable {
// 기존의 PK정의와 똑같이 정의하면된다.
@GeneratedValue
@Column(name = "PARENT_ID1")
private Long id1;
@GeneratedValue
@Column(name = "PARENT_ID2")
private Long id2;
}
다른점은 복합키를 전부 식별클래스에서 관리한다는 점이다.
복합키 엔티티에서는 @EmbeddedId 하나만 정의하여 식별 클래스를 정의하고
식별 클래스에서는 @Embeddable 를 클래스에 정의하여 식별 클래스로 등록한다.
식별 클래스는 기존의 PK 등록과 동일하게 작업하면 된다.
SELECT 는 둘다 동일하다.
4. 복합키 엔티티 조인 컬럼
복합키를 가진 엔티티와 조인을 하기위해서는 @JoinColumns 를 사용하여 복수의 @JoinColumn 를 정의해야한다.
@Data
@Entity
public class Child {
@Id
@GeneratedValue
@Column(name = "CHILD_ID")
private Long id;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "PARENT_ID1"),
@JoinColumn(name = "PARENT_ID2")
})
private Parent parent;
private String name;
}
5. 식별 클래스 필수 조건
식별 클래스로 등록하기 위해서는 필수 조건이 있다.
- Serializable 인터페이스를 상속받아야한다.
- equals, hashCode 를 필수로 구현해야한다.
- 기본 생성자가 필수로 있어야한다.
- 식별자 클래스의 접근제한자는 무조건 public 이어야한다.
equals와 hashCode, 생성자는 별도로 작성하지 않아도 자동으로 생성되니 수기로 등록할 필요는 없다.