티스토리 뷰
다대다 관계
의 경우 실무에서는 지양해야 하는 방식이라고 하지만, 그냥 사용하지 않는 것이 아니라 그 이유는 알고 있어야 하므로 다대다 관계
에 대해서 정리 해보려고 한다. 샘플 코드는 가장 아래에 있는 링크를 참조하면 된다.
1. 객체와 테이블의 차이
객체
객체는 컬렉션
을 사용해서 객체 두 개로 다대다 관계
가능하다.
관계형 DB
관계형 DB는 정규화된 테이블 두 개로 다대다 관계
를 표현할 수 없다. 그러므로 연결 테이블
을 추가해서 일대다 - 다대일 관계
로 풀어내야 한다.
2. 단방향
@ManyToMany
어노테이션을 사용하여 다대다 관계
를 매핑한다.
엔티티 예시
@JoinTable
: 연결 테이블
지정
@Entity
@Table(name = "ORDERS")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order {
@Id @GeneratedValue
private Long id;
@ManyToMany
@JoinTable(name = "ORDER_ITEM")
private List<Item> items = new ArrayList<>();
}
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Item {
@Id @GeneratedValue
private Long id;
private String name;
}
연결 테이블 생성 확인
3. 양방향
엔티티 예시
@Entity
@Table(name = "ORDERS")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order {
@Id @GeneratedValue
private Long id;
@ManyToMany
@JoinTable(name = "ORDER_ITEM")
private List<Item> items = new ArrayList<>();
}
양방향 관계를 위한 mappedBy
속성 추가
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Item {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToMany(mappedBy = "items")
private List<Order> orders = new ArrayList<>();
}
4. 한계와 극복
한계
우선, 연결 테이블
은 실무에서 단순히 연결만 하고 끝나지 않을 가능성이 높다. 예를 들어, 주문 시간이나 수량과 같은 데이터가 추가될 수 있다. 이렇게 컬럼을 추가하면 더는 @ManyToMany
를 사용 할 수 없다. 왜냐하면 새로 추가될 컬럼들은 엔티티에 매핑할 수 없기 때문이다.
극복 방법
이러한 한계를 극복하기 위한 방법은 연결 테이블용 엔티티
를 추가하는 것이다. 즉, 연결 테이블
을 엔티티로 취급한다. 그리고, 다대다 관계
를 일대다 - 다대일 관계
으로 변경한다.
엔티티 예시
@Entity
@Table(name = "ORDERS")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order {
@Id @GeneratedValue
private Long id;
@OneToMany(mappedBy = "order")
private List<OrderItem> orderItems = new ArrayList<>();
}
연결 테이블용 엔티티
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class OrderItem {
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "order_id")
private Order order;
@ManyToOne
@JoinColumn(name = "item_id")
private Item item;
}
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Item {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "item")
private List<OrderItem> orderItems = new ArrayList<>();
}
ERD 예시
연결 테이블과 달리, 별도의 id가 존재한다.
테이블 생성 확인
쿼리를 통해서도 id를 확인할 수 있다.
샘플 코드 🤓
참고 자료 🙇♂️
'JPA' 카테고리의 다른 글
[JPA] 값 타입(value object) 컬렉션 (0) | 2023.06.06 |
---|
댓글