티스토리 뷰

Study/Spring

스프링 정리(4)

giiro 2021. 8. 21. 23:01

1. 상속관계 매핑


  • ORM에서 상속관계 매핑은 부모 클래스에서 Inheritance 어노테이션을 사용합니다. 이 때 관계모델을 구현하는 방법은 아래와 같이 세 가지 방법이 있습니다.

(1) 각각의 테이블로 변환 (@Inheritance(stragy = InheritanceType.JOINED)

  • @Inheritance의 전략을 JOINED으로 설정하면 자식 테이블들을 DTYPE으로 구분하여 사용할 수 있습니다.
  • 상속받는 자식 테이블을 각각 만들고, 부모 테이블의 PK를 자식 테이블의 PK이자 FK로 사용합니다. 이를 통해 다른 테이블에서 부모 테이블만 보도록 설계할 수 있습니다.

(2) 단일 테이블로 변환 (@Inheritance(stragy = InheritanceType.SINGLE_TABLE)

  • @Inheritance의 전략을 SINGLE_TABLE로 설정하면 자식 테이블들을 통합한 단일 테이블로 사용할 수 있습니다.
  • @DiscriminatorValue("...") = 각각의 테이블들이 하나의 싱글테이블로 합쳐지기에 구분할 수 있는 값을 넣어줍니다.

(3) 서브타입 테이블로 변환 (@Inheritance(stragy = InheritanceType.TABLE_PER_CLASS)

  • @Inheritance의 전략을 TABLE_PER_CLASS로 설정하면 자식 엔티티들을 각각의 테이블로 만들어 사용합니다.
  • 여러 자식들을 조회할 때, UNION을 사용하여 성능이 저하되며 다른 여러 단점들이 존재하여 자주 사용하지 않습니다.

2. JPA 연관관계 매핑


(1) 방향

  • 방향을 선택하는 건 두 객체간의 참조가 필요한지에 따라 선택할 수 있습니다.
  • 단방향 : 둘 중 한 쪽만 참조하는 관계 (객체간의 관계)
  • 양방향 : 둘이 서로를 참조하는 관계 (테이블간의 관계)

(2) 연관관계의 주인

  • 두 객체의 연관 관계중 양방향 연관관계를 만들 때 외래 키(FK)를 관리할 쪽을 말합니다.
  • DB의 연관관계와 매핑, 외래 키(FK)를 관리합니다. 따라서 주인이 아닌쪽은 외래 키를 변경하지 못하며 읽기만 가능합니다.

(3) 다중성

  • 데이터베이스를 기준으로 다중성을 결정하며, 1:N, N:1, N:M이 있습니다. 데이터베이스에서 무조건 다(N)쪽이 외래 키(FK)를 갖습니다.
    • 다대일(N:1) : 다(N)쪽인 엔티티에 @ManyToOne을 추가해주고, @JoinColumn("반대 쪽_id")을 추가해 반대 쪽(1)의 외래키를 갖습니다.
    • 일대다(1:N) :  일대다(단방향)는 다대일의 반대 입장이므로 같은 것이라고 생각할 수 있지만 이는 다(N)쪽이 아닌 일(1)쪽에 연관관계의 주인을 두는 방식입니다. 이는 일(1)만 수정했을 때, 다(N)쪽에서도 수정이 생겨 쿼리가 발생하는 문제가 생기며 그냥 다대일(N:1)양방향 연관 관계를 매핑하는게 추후에 유지보수에도 수월하다고합니다. 일대다 단방향 매핑의 위험성과 관련해서  링크를 참고했습니다.
    • 일대일(1:1) : 주 테이블에 외래키를 넣을 수도 있고, 대상 테이블에 외래 키를 넣을 수 있습니다. 하지만 보통 일대일이라고 정했다면 주 테이블에 외래 키를 두는 게 더 낫습니다.
    • 다대다(N:M) : 학생ID를 PK로 갖는 학생 테이블과 수업ID를 PK로 갖는 수업 테이블의 관계를 생각해보면 학생 테이블의 입장에선, 한 학생은 여러 개의 수업을 들을 수 있으므로 1 : M 관계를 갖으며 수업 테이블의 입장에선, 한 수업을 여러 학생에게 선택될 수 있으므로 1 : N관계를 갖기에 서로의 관계는 N : M 입니다. 따라서 이를 연관관계로 매핑 시에는 두 테이블 사이에 양쪽의 PK를 FK로 갖는 연결 테이블을 만들어 사용합니다.

 

3. JPA 엔티티 설계


(이 부분은 강의를 들으며 정리한 내용입니다.)

  • Setter을 제거하고, 생성자에서 값을 초기화해 변경 불가능한 클래스를 만들어야합니다. ( JPA 구현 라이브러리에서 생성자를 필요로 하기때문에)
    • → 엔티티나 임베디드 타입은 기본생성자를 public보다는 protected로 설정하는게 안전합니다.
  • 모든 연관관계에서 fetch전략을 지연로딩(LAZY)으로 설정해야합니다.
    • @...ToOne의 경우, fetch 전략 디폴트가 즉시로딩(EAGER)로 되어있으므로 어떤 SQL이 실행될지 추적하기 어렵기 때문에 (@OneTo...의 디폴트는 LAZY이기에 따로 설정안해도 됨.)
  • 컬렉션은 null문제 해결을 보장하기위해 필드에서 초기화하는 것이 안전합니다.

 

4. 테이블 컬럼명 생성 전략


(1) 카멜 케이스 → 언더스코어(memberPoint member_point)

(2) .(점) → _(언더스코어)

(3) 대문자 → 소문자

 

5. 영속성 전이 (JPA casacade)


  • @...To...( cascade = CascadeType.ALL)
  • Type종류로는 ALL, PERSIST, REMOVE, MERGE, REFRESH, DETACH가 있으나 자주 사용하는 건 세 개 정도입니다.
    • ALL : 모두 적용 (PERSIST + REMOVE + ...)
    • PERSIST : 영속
    • REMOVE : 삭제
  • 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티들도 함께 영속 상태로 만들거나 삭제하는 경우에 사용합니다. 이는 엔티티를 영속화할 때 연관된 엔티티들도 함께 영속화해준다는 점에서 편리함을 제공하는 것이지 연관관계를 매핑하는 것과는 상관이 없습니다.
  • 예를 들어, Parent → children의 관계가 CascadeType.ALL로 설정되어 있다면 parent를 영속화할 때 children도 같이 영속화 됩니다.

 

6. SQL vs JPQL

  • JPA를 사용하여 엔티티 객체를 개발할 때, DB테이블을 몰라야합니다. 따라서 이 부분에서 두 개의 차이를 알 수 있습니다.
    • SQL : DB 테이블을 대상으로 쿼리를 날림.
    • JPQL : 엔티티 객체를 대상으로 쿼리를 날림.

 

'Study > Spring' 카테고리의 다른 글

스프링 정리(3)  (0) 2021.08.13
스프링 정리(2)  (0) 2021.08.08
스프링 정리(1)  (0) 2021.08.03
IOC, DI, 컨테이너  (0) 2021.01.14
회원 도메인 개발 (순수 자바코드로)  (0) 2021.01.14
댓글