Develop/JPA

[자바 ORM 표쥰 JPA 프로그래밍] 14일차 - 복합키 엔티티

자라선 2021. 8. 27. 20:21

데이터베이스에서 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, 생성자는 별도로 작성하지 않아도 자동으로 생성되니 수기로 등록할 필요는 없다.