이미 🙆♂️❤️🙅♀️ 짝사랑부터 연애까지 (JPA 연관관계) 에 대하여 작성한 글이 있다.
하지만, 이건 개념 만 잡아논거라 정확히 어떤 상황에서 어떻게 써야할지 감이 잡히지 않는다.
좀 더 확실하게 JPA 연관관계에 대해서 이해해보고자 작성한다.
정리하면, 어떤 상황이 가정되었을 경우" 나는 그걸 연관관계로 만들 수 있을까? "라는 질문을 스스로에게 던진 결과가" 나는 만들지 못한다. "였기에 다시 하기로 했다.
하나의 엔티티가 여러 개의 다른 엔티티를 참조하는 관계
예: 한 회원이 여러 주문을 가질 수 있다
하나의 엔티티가 하나의 다른 엔티티만을 참조하는 관계
예: 회원과 회원 상세 정보가 1:1로 연결될 때
여러 엔티티가 하나의 엔티티를 참조하는 관계
예: 여러 주문이 하나의 회원을 참조
( 상당히 복잡한 주제이므로, 위 소제목을 클릭하여 링크를 확인 )
여러 엔티티가 서로 여러 엔티티를 참조하는 관계
예: 상품은 여러 태그를 가질 수 있고, 태그도 여러 상품에 붙을 수 있다
우리는 음료 전문 온라인 쇼핑몰을 운영하고 있다.
이 쇼핑몰에서는 단 세 가지 상품만 판매한다.
- 콜라(제로)
- 사이다(제로, 에너지)
- 이온음료(에너지)
------------[ 회원이라면 ? ]---------------
회원은 사이트에 로그인한 뒤, 원하는 음료를 고르고 주문할 수 있다.
한 번의 주문에서 여러 종류의 음료를 선택할 수 있고,
각 음료는 원하는 수량만큼 담을 수 있다.
예를 들어,
콜라 2개, 사이다 1개, 이온음료 5개
를 한 번에 주문했다. ( 이건 1개의 주문이다. )
그리고 " 아 맞다. 사이다 2개 더 사야돼. "
하면서, 사이다 2개를 추가로 주문할 수 있다. ( 이것도 1개의 주문이다. )
------------------------------------------
즉,
1명의 회원은 <여러개의 주문>이 가능하며,
주문안에 <여러개의 상품>이 들어갈 수 있다.
그리고 음료는 카테고리가 있어. ( 제로, 에너지 ) 으로 나뉘어져 있다면?
우리는 JPA 연관관계를 어떻게 작성해야할까?
상황이 발생했다.
우리는 이 상황에 따라서, 연관관계를 매핑할 줄 알아야한다.
회원이 있어야 주문을 할 수 있다. ( 회원: Member, 주문: Order )음료가 있어야 회원이 주문에 추가할 수 있다. ( Product )주문 에는 여러개의 상품이 있다. ( OrderItem )상품 별로 여러개의 카테고리 가 존재할 수 있다. ( Category )순수 자바로 표현한다면?
public class Member {
private Long id;
private List<Order> orders;
}
public class Order {
private Long id;
private List<OrderItem> orderItems;
}
public class OrderItem {
private Long id;
private Product product;
private int ea;
}
public class Product {
private Long id;
private List<Category> categories;
}
enum Category {
ZERO("제로"),
ENERGY("에너지");
private final String name;
Category(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
( 모두 단방향으로 초기 설계를 했다. )
![]()
관계형 데이터 베이스에서는 N : M 을 표현할 수가 없다.
그래서 중간테이블을 놔야 한다.
public class ProductCategory {
private Long id;
private Product product;
private Category category;
} <그래서 자바코드에 다음과 같이 추가했다.>
예를 들어,
1. 특정 사용자의 ID 번호로 주문 번호를 전부 가져오고 싶다. ( R )
2. 특정 주문번호의 모든 상품을 가져오고 싶다.
찾을 수 없다. 즉, 특정 사용자는 찾을 수 있으나 특정 사용자의 주문 목록은 가져올 수 없다. 이유는 다음과 같다. <단방향> 에서는 Member 가 Order이 있는지 모르기 때문이다.@Entity @AllArgsConstructor @NoArgsConstructor @Getter public class Member { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; } 이 부분에서 Member는 <Order>의 존재를 모른다. 그렇기에 찾지 못하는 것이다.
단방향이므로 Order 에서 가져와야한다.
이런식으로 진행하면 해당 유저의 모든 주문목록을 가져올 수 있다.
마찬 가지로
< 특정 주문번호의 모든 상품을 가져오고 싶다. >
JOIN 을 사용하여 가져오게 한다.
들은 바로는 실무에서는 QueryDSL을 주로 쓴다고한다. ( 전해들은 이야기로 )
그래서 다음에는
"왜 실무에서는 연관관계 매핑만으로는 부족한가?"
"왜 결국 QueryDSL이 선택되는가?" 를 알아보도록 하겠다.