5. 연관 관계 매핑

khs·2022년 7월 4일
0

연관 관계 매핑 종류

  • 일대일(1:1) : @OneToOne

  • 일대다(1:N) : @OneToMany

  • 다대일(N:1) : @ManyToOne

  • 다대다(N:N) : @ManyToMany

  • 단방향과 양방향

    • 데이터베이스 테이블은 외래 키 하나로 양 쪽 테이블 조인이 가능하기 때문에 단방향, 양방향을 나눌 필요가 없다.
      그러나 객체는 참조용 필드가 있는 객체만 다른 객체를 참조하는 것이 가능하다. 그렇기 때문에 두 객체 사이에 하나의 객체만 참조용 필드를 갖고 참조하면 단방향 관계, 두 객체 모두가 각각 참조용 필드를 갖고 참조하면 양방향 관계라고 한다. (엄밀하게는 양방향 관계↔️는 없고 두 객체가 단방향 참조를 각각 가져서 양방향 관계라고 칭한다.)
  • 책에서의 코드를 보면 장바구니(Cart) 엔티티가 일방적으로 회원(Member) 엔티티를 참조하고 있다. 즉 장바구니와 회원은 일대일로 매핑돼 있으며, 장바구니 엔티티가 회원 엔티티를 참조하는 일대일 단방향 매핑이다.

즉시 로딩

  • 엔티티를 조회할 때 해당 엔티티와 매핑된 엔티티도 한 번에 조회하는 것을 '즉시 로딩'이라고 한다. 일대일, 다대일로 매핑할 경우 즉시 로딩을 기본 Fetch 전략으로 설정한다. Cart.java 클래스에서 member 엔티티와 일대일 매핑 관계를 맺어줄 때 따로 옵션을 주지 않으면 아래 코드와 같이 FetchType.EAGER(즉시 로딩)로 설정하는 것과 동일하다.
	@OneToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "member_id")
	private Member member;

연관관계주인

  • 양방향 매핑에서는 '연관 관계 주인'을 잘 설정해야한다.
  • 엔티티는 테이블과 다르기 때문에 엔티티를 양방향 연관 관계로 설정하면 객체의 참조는 둘인데 외래키는 하나이므로 둘 중 누가 외래키를 관리할지를 정해야한다.
    • 연관 관계의 주인은 외래키가 있는 곳으로 설정
    • 연관 관계의 주인이 외래키를 관리 (등록, 수정, 삭제)
    • 주인이 아닌 쪽은 연관 관계 매핑 시 mappedBy 속성의 값으로 연관 관계의 주인을 설정
    • 주인이 아닌 쪽은 읽기만 가능
  • Order.java
    Order 엔티티는 OrderItem 엔티티와 일대다 매핑을 한다. 외래키가 Order_item테이블에 있으므로 연관관계의 주인은 OrderItem 엔티티이다. mappedBy의 속성으로 "order"를 적어준 이유는 OrderItem에 있는 Order에 의해 관리된다는 의미로 해석하면 된다.
	@OneToMany(mappedBy = "order")
    private List<OrderItem> orderItems = new ArrayList<>();

다대다 매핑

  • 다대다 매핑은 실무에서 사용하지 않는 매핑관계이다.
  • 관계형 데이터베이스는 정규화된 테이블 2개로 다대다를 표현할 수 없다. 따라서 연결 테이블을 생성해서 다대다관계를 일대다, 다대일 관계로 풀어낸다.

영속성 전이

  • 영속성 전이란 엔티티의 상태를 변경할 때 해당 엔티티와 연관된 엔티티의 상태 변화를 전파시키는 옵션이다.
  • 이때 부모는 One에 해당하고 자식은 Many에 해당한다. 예를 들어 Order 엔티티가 삭제되었을 때 해당 엔티티와 연관되어 있는 OrderItem 엔티티가 함께 삭제 되거나, Order 엔티티를 저장할 때 Order 엔티티에 담겨있던 OrderItem 엔티티를 한꺼번에 저장할 수 있다.
CASCADE 종류설명
PERSIST부모 엔티티가 영속화될 때 자식 엔티티도 영속화
MERGE부모 엔티티가 병합될 때 자식 엔티티도 병합
REMOVE부모 엔티티가 삭제될 때 연관된 자식 엔티티도 삭제
REFRESH부모 엔티티가 refresh되면 연관된 자식 엔티티도 refresh
DETACH부모 엔티티가 detach되면 연관된 자식 엔티티도 detach 상태로 변경
ALL부모 엔티티의 영속성 상태 변화를 자식 엔티티에 모두 전이

지연 로딩

  • 일대일, 다대일로 매핑할 경우 기본 전략인 즉시 로딩을 통해 엔티티를 함께 가지고 온다. 따라서 예를 들어 Order 엔티티를 조회할 때 자신과 다대일로 매핑된 Member 엔티티도 가지고 온다. 작성하고 있는 비즈니스 로직에서 사용하지 않을 데이터도 한꺼번에 들고 오는 것이다. -> 사용하지 않는 데이터도 한꺼번에 조회하기 때문에 성능문제가 생기고 실무에서 사용하지 않는다.

  • FetchType.LAZY 방식으로 설정할 수 있고 이처럼 지연 로딩으로 설정하면 해당 클라스를 조회했을 때 실제 엔티티 대신에 프록시 객체를 넣어둔다. 프록시 객체는 실제로 사용되기 전까지 데이터 로딩을 하지 않고, 실제 사용 시점에 조회 쿼리문이 실행된다.


Auditing

  • 실제 서비스를 운영할 때 보통 등록시간과 수정시간, 등록자, 수정자를 테이블에 넣어놓고 활용을 한다. Spring Data Jpa에서는 Auditing 기능을 제공하여 엔티티가 저장 또는 수정될 때 자동으로 등록일, 수정일, 등록자, 수정자를 입력해준다.
profile
권혁상입니다. 행복코딩^_^

0개의 댓글