@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name="member_id")
private Long id;
@NotEmpty
private String name;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
}
@Entity
@Getter @Setter
public class Order {
@Id @GeneratedValue
@Column(name="order_id")
private Long id;
@ManyToOne
@JoinColumn(name="member_id")
private Member member;
}
현재 위의 코드를 보면 Member와 Order 객체가 있다. 연관 관계는 서로가 서로를 참조하는 양방향이고 Order가 N
Member가 1인 N:1 (다대일)로 이루어져 있다.
@JoinColumn
외래키를 연결하는 어노테이션이다. 위의 코드에서 Order객체에 작성되어 있다. name 속성은 외래 키의 이름을 알려준다. 즉 외래키를 연결하는 것이다. 우리가 코드를 작성하여 작업할 때 member를 사용하지만 데이터 베이스에서는 Order 테이블에 member가 저장되는 것이 아니라 외래 키인 member_id를 사용하여 작업한다. 여기서 의문점 Member에 있는 orders에 @JoinColumn을 작성을 하면 즉 Member가 외래키를 들고 있어도 되는 거 아닌가?? 왜 Order가 외래키를 들고 있게 해 준 거지??? 이거 알려주는 블로그 몇 없다. 거의 없다. 책이랑 인강이랑 블로그들 정보 싹싹 모아서 정리해 보겠다.
일단 정확한 데이터 베이스를 나타내지는 않지만 설명을 위해 만들어보았다. 먼저 연관 관계를 사용해야 하는 이유는 연관 관계를 사용하지 않으면 파란색 네모와 같이 중복되는 정보들을 반복하여 작성해서 테이블 크기가 옆으로 계속 늘어난다. 그림은 매우 간략화한 것이다. 실제에서는 방대한 양의 주문이 들어오고 Member의 필드들이 존재할 수 있다. 외래키를 사용하면
매우 간략해졌다. 외래키를 사용하는 이유였다. 위의 그림은 Order가 외래키를 들고 있다. 다시 처음으로 돌아가서 Member는 1 Order는 N의 관계였다. 멤버 한 명이 여러 가지의 주문을 할 수 있기 때문이다. 여기서 외래키(member_id)를 Order가 들고 있어야 하는 이유가 있다.
Member가 외래키를 갖게 되는 상황이면? Te___ho가 주문한 Order 상품만큼 id(FK)가 계속 늘어난다. 파란 박스에 지금은 3개만 있지만 주문 100개 하면 그때는 100개의 외래키를 테이블에 생성해주어야 한다. 연관 관계를 사용해야 하는 이유를 설명하면서 연관 관계를 사용하지 않으면 파란색 네모와 같이 중복되는 정보들을 반복하여 작성해서 테이블 크기가 옆으로 계속 늘어난다.라고 했는데 지금 예시는 연관관계를 사용해도 테이블 크기가 옆으로 계속 늘어난다.
결론: 외래키는 N:1 상황에서 N에 존재하여야 한다.
@MappedBy
사실 여기서부터는 조금 흔한 글이다. 위의 예시인 Order와 Member는 서로 @ManyToOne, @OneToMany로 연결되어 있다. 양방향 연관관계이다. 근데 사실 양방향 연관관계는 없다. 애플리케이션에서 로직적으로 잘 처리해 놔서 양방향인 것처럼 보이지만 사실 단방향 두 개가 있는 것이다. 하지만 실제 데이터베이스 테이블에서는 외래키 하나로 양방향 연관관계를 맺는다. 단방향 두 개인 연관관계에서 연관관계 주인을 설정해주어야 한다. 왜 필요하냐 가장 간단한 예로 Member가 한 Order를 수정하려 한다. 이때 Member의 orders리스트에서 꺼내와서 수정을 해야 할까 Order에서 수정해야 할까? 이러한 이유로 연관 관계의 주인이 필요하다. 주인은 등록, 수정, 삭제를 할 수 있고 반대쪽은 조회만 가능하게 만드는 것이다. 이때 사용하는 것이 @MappedBy다. 주인이 아닌 곳에 작성하고 name속성을 반대편의 필드명을 작성해 주면 된다. 그렇다면 연관관계의 주인은 어느 쪽을 해야 할까?? 외래키가 있는 곳을 연관관계의 주인으로 설정해 준다. 즉 N쪽을 연관 관계의 주인으로 설정한다. 이유는 반대로 설정하면 데이터 베이스의 쿼리문이 예상치 못하게 나올 경우가 있고 테이블 설계상 깔끔하지 않다.
결론: 양뱡향 N:1 상황에서 외래키, 연관관계 주인은 N 쪽으로 설정해준다.
'Spring' 카테고리의 다른 글
[Spring JPA] 영속성 컨텍스트 완벽 이해!, 연관 관계 주인 mapping (cascade와 차이?) (0) | 2023.03.30 |
---|---|
[Spring] JPA란? (간단정리) (0) | 2023.02.04 |
[Spring] Gradle vs Maven (빌드? 빌드 도구?) (0) | 2022.12.29 |
[Spring] 웹 스코프 (request) & 프록시 (2) | 2022.08.11 |
[Spring] 빈 스코프 (프로토타입) (0) | 2022.08.09 |