[JPA] JPA에서 복합키와 식별관계 매핑하기

윤재열·2022년 5월 6일
0

JPA

목록 보기
9/21
post-custom-banner

DB의 설계상에서 key를 단일 키만 사용하는 경우는 거의 없습니다.
대부분 복합 key를 사용하여 DB설계를 하고 있습니다.
그래서 JPA에서 복합 키를 어떻게 표현할 수 있는지 공부해 보겠습니다.

식별, 비식별 관계

DB에서는 FK(외래 키)가 기본 키에 포함되는지 여부에 따라 식별,비식별 관계로 구분됩니다.

보통 비식별 관계를 주로 사용하고 필요한 상황에서 식별 관계를 사용합니다.

  • 식별 관계 : 부모 테이블의 기본 키를 받아 자식 테이블의 기본 키+외래 키 로 사용합니다.
  • 비식별 관계 : 부모 테이블의 기본 키를 받아 자식 테이블의 외래키 로 사용
    • 필수적 비식별 관계 : 외래 키에 NULL을 허용합니다.
    • 선택적 비식별 관계 : 외래 키에 NULL을 허용합니다.

복합 키를 표현할 때는 JPA에서는 식별자 클래스를 만들어야 합니다.
그리고 식별자 클래스는 @IdClass, @EmbededId 두개의 어노테이션 중 하나를 선택해서 사용하면 됩니다.

간단하게 설명하면 @IdClass 는 DB에 가까운 방법, @EmbededId는 객체지향에 가까운 방법입니다.

식별자 클래스의 equals(),hashCode()속성 컨텍스트가 식별자를 비교할때 사용하기 때문에 반드시 오버라이딩 해줘야합니다!!

비식별 관계 매핑

@IdClass 사용

@Entity
@IdClass(ParentId.class)
public class Parent{

	@Id
    @Column(name = "parent_id1")
    private Int id1;
    
    @Id
    @Column(name = "parent_id2")
    private Int id2;
    
    private String name;
    
@NoArgsConstructor
@AllArgsConstructor
public class ParentId implements Serializable

	priavte Int id1;
    private Int id2;
    
      @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }
    
@Entity
public class child{
	
    @Id
    private Int id;
    
    @ManyToOne
    @JoinColumns({
    		@JoinColumn(name = "parent_id1", referencedColumnName = "parent_id1"),
            @JoinColumn(name = "parent_id2", referencedColumnName = "parent_id2")
	})
	
    private Parent parent;
  • 코드를 순서대로 살펴보겠습니다.

    • 복합 키를 사용하기 위해서는 식별자 클래스를 만들어야 합니다.그래서 ParentId 식별자 클래스를 생성하였습니다.

    • Parent 에서 @IdClass(ParentId.class)를 선언하여 식별자 클래스를 지정하였습니다.

      • 식별자 클래스의 필드명과 엔티티에서 사용하는 식별자의 필드명이 동일해야 합니다.
      • Serializable 인터페이스를 구현해주어야 합니다.
      • equals(),hashCode()를 구현해주어야합니다.
      • 디폴트 생성자를 선언해야합니다.
      • 클래스의 접근 제한자는 public 이어야 합니다.
    • Child에서는 복합 키 매핑을 위해 @JoinColumns를 이용하고 각각의 Key는 @JoinColumn으로 매핑해줍니다.

    • referencedColumnName 속성이 name 속성과 동일할 때 생략이 가능하나, 미지정하였을 때는 @JoinColumns에 선언된 @JoinColumn의 순서가 바뀌어 저장 될 수 있습니다.

    • referencedColumnName 속성을 지정하기를 권장 합니다.

@EmbeddedId 사용

@Entity
public class Parent{
	
    @EmbeddedId
    private ParentId id1;
    
    private String name;
    
    }
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class ParentId implements Serializable {
  
  @Column(name = "parent_id1")
  private Int id1;
  @Column(name = "parent_id2")
  private Int id2;
  
    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }
  • Parent에서 식별자 클래스 타입의 필드를 생성하고 @EmbeddedId를 사용하여 비식별 관계 매핑을 해주었습니다.
    • IdClass와는 다르게 @EmbeddedId를 적용한 식별자 클래스는 식별자 클래스에 기본 키를 직접 매핑합니다.
    • @EmbeddedId를 사용할 때는 아래의 조건과 같습니다.
      • 식별자 클래스에 @Embeddable을 사용해야합니다.
      • Serializable 인터페이스를 구현해주어야 합니다.
      • equals(),hashCode()를 구현해주어야합니다.
      • 디폴트 생성자를 선언해야합니다.
      • 클래스의 접근 제한자는 public 이어야 합니다.
profile
블로그 이전합니다! https://jyyoun1022.tistory.com/
post-custom-banner

0개의 댓글