[02.01] 내일배움캠프[Spring] TIL-63

박상훈·2023년 2월 2일
0

내일배움캠프[TIL]

목록 보기
63/72

[02.01] 내일배움캠프[Spring] TIL-63

Raw JPA 연관관계 매핑 기능

OneToOne

  • 일대일 관계를 나타내는 매핑 정보
  • 1:1 관계를 지정하기에 앞서 이것이 꼭 물리적으로 테이블이 분리되어야 하는지에 대해 생각해 봐야 한다.
  • 1:1 관계로 구성 한다는 것은 결국 하나의 목적에 부합되는 공통된 데이타를 관리한다고 볼 수 있으며 이것은 하나의 테이블에서 관리 할 수 있는 데이타일 가능성이 높다는 의미.
  • 즉, 의도적 중복이 아니라면 사용할일이 없다는 말

OneToMany

  • 일대다 관계를 나타내는 매핑 정보
  • @OneToMany가 단방향으로 쓰이면 문제가 발생할 수 있다.
    -> 이 말을 일단 연관관계의 주인이 외래키를 관리하지 않고 외래키를 다른 테이블에서 관리하는데, 따라서 불필요한 Update Query가 나간다.
  • 속도를 위해 기본적으로 FetchType 설정이 LAZY 로 설정되어 있다.
    -> 생각해봐라 난 연관관계가 딸려있는 객체의 정보가 필요없는데, 그 엔티티를 조회하는 것 만으로도 관련된 데이터가 join되어서 나오는 Eager라면... 절래절래..

ManyToOne

  • 다대일 관계를 나타내는 매핑 정보
  • fetch : 글로벌 패치 전략 설정
    • ✋ 기본이 EGEAR 로 설정되어있으나 실무에서는 기본 LAZY로 설정하는것 추천!
  • cascade : 영속성 전이 기능 사용
  • targetEntity : 연관된 엔티티의 타입 정보 설정 (targetEntity = Member.class 식으로 사용)

JoinColmn

  • 외래 키 매핑 시 사용 (Join 을 요청하기 위한 매핑정보로 쓰인다.)
  • @ManyToOne 어노테이션과 주로 함께 쓰인다. (조인대상 컬럼 지정기능을 안쓸거면 생략해도 됨)
  • name 속성은 매핑할 외래키의 이름( @JoinColum(name ="USER_ID" )
  • 어노테이션을 생략해도 외래 키가 생성됨.
    • 생략 시 외래키의 이름이 기본 전략을 활용하여 생성된다.

ManyToMany

  • 다대다 관계를 나타내는 매핑 정보 (N:M)
  • 다대다 설정을 하게되면 중간 매핑테이블(JoinTable)이 자동으로 생성된다.
  • 중간 매핑 테이블은 JPA상에서 숨겨져서(Entity 정의 없이) 관리된다.
    ✋ 매핑 테이블 관리가 불가능하여서 실무에서는 잘 사용하지 않는 기능 입니다.
    ✋ ex) Product < - ManyToMany -> Category => 둘의 id값을 갖는, 조작이 불가능한 table이 생성됨.
    User(@OneToMany) > UserProduct(MappingTable)(@ManyToOne, @ManyToOne) > Product(@OneToMany)

복합키 사용해보기

  • PK - 단일키
  • FK 2개 - 복합키 ( PK없이 )
  • 방법은 2가지가 있지만, 둘다 써보면 머리에 안들어올 것 같아서 @IdClass() 방식만 포스팅하겠다.

@IdClass

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserChannelId implements Serializable {
  private Long user;   // UserChannel 의 user 필드명과 동일해야함
  private Long channel; // UserChannel 의 channel 필드명과 동일해야함

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    UserChannelId userChannelId = (UserChannelId) o;
    return Objects.equals(getUser(), userChannelId.getUser()) && Objects.equals(getChannel(), userChannelId.getChannel());
  }

  @Override
  public int hashCode() {
    return Objects.hash(getUser(), getChannel());
  }
}
@Entity
@IdClass(UserChannelId.class)
public class UserChannel {
  ....

  @Id
  @ManyToOne
  @JoinColumn(name = "user_id")
  User user;

  @Id
  @ManyToOne
  @JoinColumn(name = "channel_id")
  Channel channel;
  ...
}

Raw JPA 기타 기능 (Cascade, orphanRemoval, Fetch)

Cascade(영속성 전이)

  • 사용위치 : 연관관계 주인의 반대편 (다대일에서 일)
    • 즉, @OneToMany 가 있는 쪽 또는 @OneToOne 도 가능
  • 사용 조건 : Ex)게시글이 삭제되면, 댓글도 전부 삭제되어야 한다.
  • 옵션 종류
    • ALL : 전체 상태 전이
    • PERSIST : 저장 상태 전이
    • REMOVE : 삭제 상태 전이
    • MERGE : 업데이트 상태 전이
    • REFERESH : 갱신 상태 전이
    • DETACH : 비영속성 상태 전이

orphanRemoval (고아 객체 제거)

  • 사용 위치 : @OneToMany 또는 @OneToOne 에서 사용 - 부모 엔티티
  • 부모 객체에서 리스트 요소삭제를 했을경우 해당 자식 객체는 매핑정보가 없어지므로 대신 삭제해준다.
    • 요건 DB 에서는 절대 알 수 없는 행동이다. (부모가 자식의 손을 놓고 버리고 간 고아 객체)

Cascade와 orphanRemoval의 차이

  • Cascade.REMOVE : 일에 해당하는 부모 엔티티를 em.remove를 통해 직접 삭제할 때,그 아래에 있는 다에 해당하는 자식 엔티티들이 삭제되는 것이다.
  • orphanRemoval=true : 위 케이스도 포함하며,일에 해당하는 부모 엔티티의 리스트에서 요소를 삭제하기만 해도 해당 다에 해당하는 자식 엔티티가 delete되는 기능까지 포함하고 있다고 생각하면 된다.
  • 즉, orphanRemoval=true 는 리스트 요소로써의 영속성 전이도 해준다는 뜻
  • 영속성 전이 최강 조합 : orphanRemoval=true + Cascade.ALL
    -> 위 2개를 함께 설정하면 자식 엔티티의 라이프 사이클이 부모 엔티티와 동일해지며, 직접 자식 엔티티의 생명주기를 관리할 수 있게 되므로 자식 엔티티의 Repository 조차 없어도 된다. (따라서, 매핑 테이블에서 많이 쓰임)

Fetch( 조회 시점 )

  • 사용 위치 : 모든 연관관계에 사용
  • fetchType=Lazy 여도 , fetch join 쿼리 수행을 통해서 즉시 join으로 불러올 수 있다.
  • 사용법
    • 기본 LAZY를 설정한 뒤에 필요할때만 fetch Join 을 수행한다.
    • 항상 같이 쓰이는 연관관계 일 경우EAGER 를 설정한다.
  • 옵션(FetchType)
    • EAGER : 즉시 로딩 (부모 조회 시 자식도 같이 조회)
    • LAZY : 지연 로딩 (자식은 필요할때 따로 조회)
profile
기록하는 습관

0개의 댓글