[JPA] 복합 키와 식별 관계 매핑

복합 키를 매핑하는 방법과 식별 관계, 비식별 관계를 매핑하는 방법을 알아보자

식별 관계 vs 비식별 관계

데이터베이스 테이블 사이에 관계는 외래 키가 기본 키에 포함되는지 여부에 따라 식별 관계비식별 관계로 구분한다.

  • 식별 관계(Identifing Relationship)
  • 비식별 관계(Non-Identifying Relationship)

식별 관계

식별 관계는 부모 테이블의 기본 키를 내려받아서 자식 테이블의 기본 키 + 외래 키로 사용하는 관계다.

주문_상품 테이블 같은 경우가 식별 관계에 해당한다.


비식별 관계

비식별 관계는 부모 테이블의 기본 키를 받아서 자식 테이블의 외래 키로만 사용하는 관계다.

비식별 관계는 외래 키에 NULL을 허용하는지에 따라 필수족 비식별 관계와 선택적 비식별 관계로 나뉜다.

  • 필수적 비식별 관계(Mandatory) : 외래 키에 NULL을 허용하지 않는다. 연관관계를 필수적으로 맺어야 한다.
  • 선택적 비식별 관계(Optional) : 외래 키에 NULL 을 허용한다. 연관관계를 맺을지 말지 선택할 수 있다.

복합 키 : 비식별 관계 매핑

식별자를 둘 이상 사용하려면 별도의 식별자 클래스를 만들어야 한다.

식별자 필드가 2개 이상이면 별도의 식별자 클래스를 만들고 그곳에 equalshashCode를 구현해야 한다.

JPA는 복합 키를 지원하기 위해 @IdClass@EmbeddedId 2가지 방법을 제공하는데 @IdClass는 관계형 데이터베이스에 가까운 방법이고 @EmbeddedId는 좀 더 객체 지향에 가까운 방법이다.


IdClass

복합 키 테이블은 비식별 관계고 부모는 복합 기본 키를 사용한다.

식별자 클래스

public class ParentId implements Serializable {
	
    private String id1;
    private string id2;
    
    public parentId() {
    }
    
    public ParentId(String id1, String id2){
    
    	this.id1 = id1;
        this.id2 = id2;
    }
    
    @Override
    public boolean equals(Object o){...}
    
    @Override
    public int hashCode(){...}


식별자 클래스의 속성명과 엔티티에서 사용하는 식별자의 속성명이 같아야 한다.

  • Serializable 인터페이스를 구현해야 한다.
  • equals, hashCode를 구현해야 한다.
  • 기본 생성자가 있어야 한다.
  • 식별자 클래스는 public이어야 한다.

@EmbeddedId

예제

@Entity
public class Parent {

	@EmbeddedId
    private parentId id;
    
    private String name;
    
    ...
}

Parent 엔티티에서 식별자 클래스를 직접 사용하고 @EmbeddedId 어노테이션을 적어주면 된다.

식별자 클래스

@Embeddable
public class parentId impllements Serializable {

	@Column(name = "PARENT_ID1")
    private String id1;
    @Column(name = "PARENT_ID2")
    private String id2;
    
    // equals, hashCode
    ...
}

@EmbeddedId를 적용한 식별자 클래스는 다음 조건을 만족해야 한다.

  • @Embeddable 어노테이션을 붙여주어야 한다.
  • Serializable 인터페이스를 구현해야 한다.
  • equals, hashCode를 구현해야 한다.
  • 기본 생성자가 있어야 한다.
  • 식별자 클래스는 public이어야 한다.

@IdClass vs @EmbeddedId

마무리하면서 @IdClass vs @EmbeddedId, 뭐가 더 좋을지 한 번 생각해보자

@IdClass와 @EmbeddedId는 각각 장단점이 있어 본인의 취향에 맞는 것을 일관성 있게 사용하면 된다.

@EmbeddedId가 객체지향에 가까운 방법이여서 더 좋아보일 수 있겠지만, 특정 상황에서 JPQL이 조금 더 길어질 수 있지만, 본인은 EmbeddedId를 선호한다.

좋은 웹페이지 즐겨찾기