자바 ORM 표준 JPA 프로그래밍 7장 정리

wannabeking·2022년 8월 29일
0

JPA

목록 보기
4/7

상속 관계 매핑

  • 객체지향의 상속이라는 개념이 관계형 데이터베이스에는 없지만 유사한 슈퍼타입, 서브타입 관계가 존재함
  • 슈퍼타입, 서브타입 논리 모델을 3가지 방법으로 구현 가능
    • 조인 전략
      • 자식 테이블이 부모 테이블의 기본 키를 기본 키 + 외래 키로 사용하는 전략
      • DTYPE 컬럼을 구분 컬럼으로 사용
      • 부모 엔터티에 다음 어노테이션 추가
      • @Inheritance(strategy = InheritanceType.JOINED)
      • @DiscriminatorColumn(name = "DTYPE") : 부모 클래스에 구분 컬럼 지정
      • 자식 엔터티들에 다음 어노테이션 추가, 부모 엔터티 상속받음
      • @DiscriminatorValue("A") : 구분 컬럼에 입력할 값 지정
      • 장점 : 정규화, 외래 키 참조 무결성 제약조건 활용, 효율적인 저장공간
      • 단점 : 쿼리에 조인, INSERT 두 번 실행
    • 단일 테이블 전략
      • 테이블을 하나만 사용하면서 구분 컬럼으로 어떤 자식 데이터가 저장되었는지 구분
      • 자식 엔터티가 매핑한 컬럼은 모두 null 허용, 테이블 하나라 컬럼 많아짐
      • 부모 엔터티에 다음 어노테이션 추가
      • @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
      • @DiscriminatorColumn(name = "DTYPE")
      • 자식 엔터티들에 다음 어노테이션 추가, 부모 엔터티 상속받음
      • @DiscriminatorValue("A")
      • 장점 : 조인이 필요 없어 조회 빠름
      • 단점 : 엔터티 매핑 컬럼 모두 null 허용해야 함, 테이블 커져서 상황에 따라 조회 느림
    • 구현 클래스마다 테이블 전략
      • 자식 엔터티마다 테이블 생성
      • 부모 엔터티에 다음 어노테이션 추가
      • @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
      • 일반적으로 추천하지 않는 전략
    • @MappedSuperclass
      • 데이터베이스상에서는 부모, 자식을 매핑하지 않고 부모 클래스를 상속받는 자식 클래스에게 매핑 정보만 제공
      • 부모 클래스에 다음 어노테이션 추가, 추상 클래스로 생성 (엔터티 아님)
      • @MappedSuperclass
      • 자식 엔터티는 부모 클래스 상속받음
      • @AttributeOverride(s) : 물려받은 매핑 정보 재정의, name 속성은 부모 컬럼, column 속성은 재정의할 컬럼
      • @AssociationOverride(s) : 연관관계 재정의
      • 부모 클래스는 엔터티가 아니라 em.find(), JPQL 사용 불가
      • 공통 속성 효과적으로 관리 가능 (생성일자, 수정일자 등)


복합 키와 식별 관계 매핑

  • 식별 관계
    • 외래 키가 기본 키에 포함되는 관계 (자식 테이블의 부모 테이블의 기본 키를 기본 키 + 외래 키로 사용)
    • 부모, 자식, 손자 관계에서 손자가 부모를 한번에 JOIN 할 수 있음
  • 비식별 관계
    • 자식 테이블이 부모 테이블의 기본 키를 외래 키로만 사용
    • 필수적 비식별 관계는 외래 키에 NULL 허용하지 않음, 연관관계 필수
    • 선택적 비식별 관계는 외래 키에 NULL 허용, 연관관계 선택
  • 복합 키
    • 식별자를 둘 이상 사용하기 위해서는 별도의 식별자 클래스 생성해야 함
    • 식별자 클래스는 다음과 같은 제한사항이 존재
      • 식별자 클래스의 속성명과 엔터티에서 사용하는 식별자의 속성명 같아야 함
      • Serializable 구현해야 함
      • equals, hashCode 구현해야 함
      • public 이어야 함
      • 기본 생성자 있어야 함
    • @IdClass
      • 관계형 데이터베이스에 가까움
      • 부모 클래스에 다음 어노테이션 추가
      • @IdClass(ParentId.class)
      • 부모 클래스에 다음 필드 생성
      • @Id @Column(name = "parent_id1") private String id1;
      • @Id @Column(name = "parent_id2") private String id2;
      • 자식 클래스의 부모 클래스 필드에 다음 어노테이션 추가
      @ManyToOne
      @JoinColumns({
      	@JoinColumn(name = "parent_id1", referencedColumnName = "parent_id1"),
          @JoinColumn(name = "parent_id2", referencedColumnName = "parent_id2")
      })
      private Parent parent;
    • @EmbeddedId
      • 객체지향에 가까움
      • 부모 클래스의 식별자 필드에 다음 어노테이션 추가
      • @EmbeddedId
      • 식별자 클래스에 다음 어노테이션 추가
      • @Embeddable
      • 자식 클래스의 부모 클래스 필드에 다음 어노테이션 추가
      • @MapsId("parentId")
      • 특정 상황에 @IdClass보다 JPQL이 조금 길어질 수 있음 (p.id.id1 vs p.id1)
    • 일대일 식별 관계에서는 복합 키로 구성하지 않아도 됨, 부모 기본 키를 자신의 기본 키로 사용
    • 데이터베이스 설계 관점에서 식별 관계보다는 비식별 관계 선호
    • 되도록 Long 대리 키 + 비식별 사용하자


조인 테이블

  • 조인 컬럼 사용 (외래 키)
    • 선택적 비식별 관계에서는 외래 키에 null을 허용하므로 OUTER JOIN을 사용해야 함
  • 조인 테이블 사용
    • 조인 한번 더 해야하는 단점 존재, 일반적으로 다대다 관계에서 중계 테이블로 사용
    • 부모 클래스의 자식 필드에 다음과 같은 어노테이션 추가
    @OneToOne
    @JoinTable(name = "parent_child",
    	joinColumns = @JoinColumn(name = "parent_id"),
      inverseJoinColumns = @JoinColumn(name = "child_id"))
    private Child child;
    • 양방향으로 매핑하려면 다음과 같이
    @OneToOne(mappedBy = "child")
    private Parent parent;
    • 조인 테이블에 컬럼 추가할 수 없음, 컬럼 추가하고 싶으면 새로운 엔턴티 만들어서 사용


엔터티 하나에 여러 테이블 매핑

  • @SecondaryTable 사용
    • 엔터티에 다음 어노테이션 추가
    • @SecondaryTable(name = "추가할테이블명", pkJoinColumns = @PrimaryKeyJoinColumn(name = "추가할테이블명_id"))
    • 테이블로 빼고싶은 필드에 다음 어노테이션 추가
    • @Column(table = "추가할테이블명")
    • 더 많은 테이블 매핑하고 싶으면 다음 어노테이션 사용
    • @SecondaryTables({})
    • 권장되지 않는 방법, 테이블당 엔터티를 각각 만드는 것을 권장


profile
내일은 개발왕 😎

0개의 댓글