JPA에 대해 알아보자 : 7장 고급매핑

ParkIsComing·2023년 7월 10일

Spring

목록 보기
9/21
post-thumbnail

책 [자바 ORM 표준 JPA 프로그래밍]을 참고하여 작성하였습니다.

7장 고급 매핑

7.1 상속 관계 매핑

테이블로 구현할 때는 3가지 전략을 사용할 수 있다.

  1. 조인 전략
    : 각각을 모두 테이블로 만들고 조회할 때는 조인을 사용
  2. 통합 테이블로 변환
    : 테이블을 하나만 사용해서 표현
  3. 서브타입 테이블로 변환
    : 서브타입마다 하나의 테이블로 표현

7.1.1 조인 전략

  • 엔티티 각각을 테이블로 만들고 자식 테이블이 부모 테이블의 기본키를 받아 기본키 + 외래키로 사용한다.
  • 조회시에는 조인을 사용한다.
  • 테이블은 타입의 개념이 없으므로 타입을 구분하는 컬럼이 필요하다.
  • 장점
    • 테이블이 정규화된다.
    • 외래키 참조 무결성 제약조건 활용 가능
    • 저장공간의 효율적인 사용
  • 단점
    • 조회 시에 조인이 많이 사용됨

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name= "DTYPE") //부모클래스에 구분 컬럼을 지정. 이 컬럼으로 자식 테이블을 구분한다.
public abstract class Item{
  @Id @GeneratedValue
  @Column(name = "ITEM_ID")
  private Long id;

  private String name;
  private int price;
}

@Entity
@DiscriminatorValue("A") //구분 컬럼에 입력할 값을 설정한다.
public class Album extends Item {
  private String artist;
}

@Entity
@DiscriminatorValue("M") 
public class Movie extends Item {
  private String director;
  private String actor;
}

7.1.2 단일 테이블 전략

  • 조회시에 조인을 사용하지 않아도 되기 때문에 가장 빠르다
  • 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다.
  • 구분 컬럼을 꼭 사용해야 (따라서 @DiscriminatorColumn 지정 필수)

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name= "DTYPE") //부모클래스에 구분 컬럼을 지정. 이 컬럼으로 자식 테이블을 구분한다.
public abstract class Item{
  @Id @GeneratedValue
  @Column(name = "ITEM_ID")
  private Long id;

  private String name;
  private int price;
}

@Entity
@DiscriminatorValue("A") //구분 컬럼에 입력할 값을 설정한다.
public class Album extends Item {
  private String artist;
}

@Entity
@DiscriminatorValue("M") 
public class Movie extends Item {
  private String director;
  private String actor;
}

7.1.3 구현 클래스마다 테이블 전략

  • 비추
  • 자식엔티티마다 테이블 만들기
  • 자식테이블 안에 필요한 칼럼이 다 있다.
  • 구분컬럼 사용X

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Item{
  @Id @GeneratedValue
  @Column(name = "ITEM_ID")
  private Long id;

  private String name;
  private int price;
}

@Entity
public class Album extends Item {
  private String artist;
}

@Entity
public class Movie extends Item {
  private String director;
  private String actor;
}

7.2 @MappedSuperClass

  • 이전과는 다르게 부모 클래스는 테이블과 매핑하지 않고 자식클래스에게만 매핑 정보를 제공하고 싶을 때 사용한다.
  • 부모로부터 상속받은 매핑정보를 재정의하려면 @AttributeOverrides 또는 @AttributeOvverride 사용
  • 연관관계를 재정의하려면 @AssociationOverrides 또는 @AssociationOverride 사용


@MapepdSuperClass
public abstract class BaseEntity {
  @Id @GeneratedValue
  private Long id;
  private String name;
}

@Entity
public class Member extends BaseEntity{
  private String email;
}

@Entity
public class Seller extends BaseEntity {
  private String shopName;
}

7.3 복합키와 식별관계 매핑

7.3.1 식별 관계와 비식별 관계

식별관계

  • 부모 테이블의 기본키를 내려받아서 자식 테이블의 기본키 & 외래키로 사용

비식별 관계

  • 부모 테이블의 기본키를 내려받아서 자식테이블의 기본키로만 사용하는 관계
  1. 필수적 비식별 관계
  • 외래키에 null을 허용하지 않는다
  • 연관관계를 필수적으로 맺어야 한다.
  1. 선택적 비식별 관계
  • 외래키에 null을 허용한다.
  • 연관관계를 선택적으로 맺을 수 있다.

최근에는 비식별 관계를 주로 사용하고 필요한 곳에만 식별 관계를 채택하는 추세.

7.3.2 복합키 : 비식별 관계 매핑

  • JPA는 영속성 컨텍스트에 엔티티를 보관할 때 엔티티의 식별자를 키로 사용
  • 식별자 구분에는 equalshashCode 사용하여 동등성 비교
  • JPA는 복합키 지원을 위해 @IdClass@EmbeddedId 제공

@IdClass

  • (식별자 클래스의 속성명) = (엔티티에서 사용하는 식별자의 속성명) 을 만족해야 한다.
  • Serializable 인터페이스를 구현해야 한다.
  • equals, hashCode를 구현해야 한다.
  • 기본 생성자가 있어야 한다.
  • 식별자 클래스는 public이어야 한다.

[예시]

다음과 같은 테이블을 가정해보자.

▼부모 클래스

@Entity
@IdClass(ParentId.class)
public class Parent {
	@Id
    @Column(name = "PARENT_ID1")
    private String id1;
    
    @Id
    @Column(name = "PARENT_ID2")
    private String id2;
    
    private String name;
}

▼식별자 클래스

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 obj) {
        ...
    }

    @Override
    public int hashCode() {
        ...
    }
}

다음과 같이 조회할 수 있다.

ParentId parentId = new ParentId("myId1", "myId2");
Parent parent = em.find(Parent.class, parentId)

▼자식 클래스

@Entity
public class Child{
    @Id
    private String id;
    
    @ManyToOne
    @JoinColumns({
            @JoinColumn(name="PARENT_ID1",
                    referencedColumnName =  "PARENT_ID1"),
            @JoinColumn(name = "PARENT_ID2",
                    referencedColumnName =  "PARENT_ID2")
    })
    private Parent parent;
}

@EmbeddedId

7.3.3 복합키 : 식별 관계

7.4 조인 테이블

db 테이블의 연관관계를 설명하는 방법
1. 외래키를 이용한 조인 컬럼
2. 조인 테이블 : 주로 다대다 관계를 일대다, 다대일 관계로 풀어내기 위해 사용 (a.k.a 연결테이블, 링크테이블)

0개의 댓글