Zero to Hero
article thumbnail
Published 2021. 5. 16. 17:40
JPA Study 03 Programming

 

책을 읽고 배운 내용을 정리한다.

 

맵핑은 다대일 단방향부터 생각하자

- JPA는 다양한 연관관계에 대한 맵핑 방법을 제공한다.

- 그중 가장 기본이 되는 방법은 다대일 단방향 맵핑이다.

- 2개의 테이블을 JOIN 했을 때 가장 연상하기도 쉽고 DB 관점에서도, 객체 관점에서도 개발자에게 익숙하다.

- 양방향 맵핑은 필요한 경우에만 만들어주면 된다.

- 단방향, 양방향의 차이는 객체 그래프 탐색의 루트를 한쪽에서만 할 수 있을지, 양 쪽에서 다 가능하게 할지의 차이기 때문이다.

 

다대다 맵핑

@Entity
@Data
public class Member {
    @Id
    @Column(name = "MEMBER_ID")
    private String id;

    @Column
    private String username;

    // 다대다 매핑
    @ManyToMany
    @JoinTable(name = "MEMBER_PRODUCT",
            joinColumns = @JoinColumn(name = "MEMBER_ID"),
            inverseJoinColumns = @JoinColumn(name = "PRODUCT_ID"))
    private List<Product> products = new ArrayList<>();

}

- 위와 같이 설정하면 다대다 맵핑도 가능하다.

- 주인 엔티티에서 위와 같이 설정해주면 다대다 단방향, 다른 엔티티에서 mappedBy로 연관 관계를 맺어주면 다대다 양방향이 된다.

문제점

- 위 방법처럼 다대다 맵핑을 구현할 수 있지만, 실제 상황에선 고려해야 하는 점이 많다.

- 우선 다대다 관계라는 것은 그 중간에 (일대다, 다대일) 역할을 하는 테이블을 만들 수 있다는 점인데, 일반적으로 이 테이블 또한 여러 가지 방법으로 사용할 수 있다.

- 고객과 상품은 다대다 관계이다.

- 고객이 상품을 주문하고 그것을 비즈니스 로직으로 처리할 땐 주문정보 라는 테이블(엔티티)이 자연스럽게 필요하다.

- 주문정보 테이블엔 어떤 고객이 어떤 상품을 주문했는지 뿐만 아니라 몇 개 주문했고 가격은 얼마인지 등 다른 데이터 또한 들어갈 수 있다.

- RDB 관점에서도 다대다 JOIN은 없기 때문에 중간 테이블을 분리한다.

 

중간 테이블 사용하기

@Entity
@Data
@IdClass(MemberProductId.class)
public class MemberProduct {


    @Id
    @ManyToOne
    @JoinColumn(name = "MEMBER_ID")
    private Member member;

    @Id
    @ManyToOne
    @JoinColumn(name = "PRODUCT_ID")
    private Product product;


    @Column
    private int orderAmount;
}
// 다대다 관계를 맵핑하기 위한 중간 테이블의 복합키 클래스
// 이것을 DB 용어로 식별 관계라고 한다.

@Data
public class MemberProductId implements Serializable {

    private String member;
    private String product;

    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

    @Override
    public int hashCode() {
        return Objects.hash(member, product);
    }
}

- 다대다 관계를 맵핑하기 위해 회원에 대해선 일대다, 상품에 대해선 다대일 관계를 가지는 MemberProduct라는 중간 테이블을 만들었다.

- 중간 테이블의 PK는 양쪽 테이블의 PK를 더한 복합 키이다.

- 이 복합 키를 관리하는 Class를 따로 만들고 equals, hashcode, 직렬화 구현 등을 다 해줘서 다대다 맵핑을 관리하는 방법이 있다.

- 이렇게 부모 테이블의 기본키를 받아서 자식 테이블의 기본키 + 왜래 키로 사용하는 것을 식별 관계라고 한다.

- 굉장히 복잡하다

 

- 그래서 이렇게 복합키로 중간 테이블을 관리하지 말고, 그냥 중간 테이블에 아무런 비즈니스적 의미가 없는 연속된 숫자를 키로 사용하면 편리하다.

- 이런 방법을 비식별 관계라고 한다.

- 많은 JPA 코드에서 Entity 클래스가 아무런 이유 없이 "private Long id" 를 가지는 것이 아닌 걸 알 수 있다.

 

'Programming' 카테고리의 다른 글

@cache  (0) 2021.06.28
Flask 사용법  (2) 2021.05.17
JPA Study 02  (0) 2021.05.15
JPA Study 01  (0) 2021.05.15
DB 예약어(MySQL, MariaDB)  (0) 2021.05.14
profile

Zero to Hero

@Doljae

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!