목차
테이블 설계
다대다 연관관계를 고객이 주문한 음식(Food)과 고객(Member)을 예시로 설명하겠습니다.
- 여러 가지의 음식(Food)은 여러 명의 고객(Member)에게 주문될 수 있다.
- 음식(Food) : 고객(Member) = N : M
단방향 연관관계를 위한 추가 조건은 다음과 같습니다.
- Food Entity는 Food.memberList 필드를 통해 음식을 주문한 고객(List<Member)에 접근할 수 있다.
- Member Entity는 Food Entity에 직접 접근할 수 없다.

Entity 관계 매핑
- Food Entity
- 다대다 단방향 연관관계에서 외래키의 주인입니다.
@Entity
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToMany
@JoinTable(name = "orders", // 중간 테이블 생성
joinColumns = @JoinColumn(name = "food_id"),
inverseJoinColumns = @JoinColumn(name = "member_id"))
private List<Member> memberList = new ArrayList<>();
public void addMemberList(Member member) {
this.memberList.add(member);
}
// constructor, getter, setter, ...
}
- Member Entity
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// constructor, getter, setter, ...
}
- 다대다 단방향 매핑에서는 외래키의 주인에 해당하는 Entity에 반대편 Entity를 Collection 프레임워크로 감싼 형태의 참조 필드로 작성합니다.
- 참조 필드 위에
@ManyToOne
애노테이션과@JoinColumn
애노테이션을 추가로 작성합니다. @JoinColumn
의name
속성은 다대다 관계를 풀어줄 연결 테이블의 이름을 지정합니다.@JoinColumn
의joinColumns
속성은 다대다 연관관계에서 외래키의 주인에 해당하는 외래키를 매핑합니다.@JoinColumn
의inverseJoinColumns
속성은 다대다 연관관계에서 외래키의 주인에 해당하지 않는 외래키를 매핑합니다.- 위의 Entity 관계를 적용하여 테이블을 생성하였을 때, 실행되는 SQL은 아래와 같습니다.
CREATE TABLE FOOD (
ID BIGINT NOT NULL AUTO_INCREMENT,
NAME VARCHAR(255),
PRICE FLOAT(53) NOT NULL,
PRIMARY KET (ID)
);
CREATE TABLE MEMBER (
ID BIGINT NOT NULL AUTO_INCREMENT,
NAME VARCHAR(255),
PRIMARY KET (ID)
);
CREATE TABLE ORDERS (
FOOD_ID BIGINT NOT NULL,
MEMBER_ID BIGINT NOT NULL
);
ALTER TABLE ORDERS
ADD CONSTRAINT FKpktxwhj3x9m4gth5ff6bkqgeb
FOREIGN KEY (MEMBER_ID)
REFERENCES MEMBER (ID)
ALTER TABLE ORDERS
ADD CONSTRAINT FK5g4j2r53ncoltplogbnqlpt30
FOREIGN KEY (FOOD_ID)
REFERENCES FOOD (ID)
- @ManyToMany의 한계점
@JoinColumn
으로 인해 연결 테이블이 Orders 테이블이 생성되었습니다.- 자동 생성된 Orders 테이블은 food_id와 member_id만을 컬럼으로 가지고 있는데, 실제 중간 테이블을 활용하기 위해서는 주문 시각이나 주문 번호(order_id)등의 추가 정보가 필요할 수 있습니다.
- 또, 연결 테이블인 orders 테이블은 숨겨진 테이블이기 때문에 예상할 수 없는 쿼리들이 실행될 수 있습니다.
- @ManyToMany의 한계점 해결 방법
- 연결용 테이블의 Entity를 만들어 줍니다.
@ManyToMan
y를@ManyToOne
과@OneToMany
를 활용하여 일대다, 다대일 관계로 풀어줍니다.- 위 방식은 여기에서 설명하겠습니다.
Entity 관계 사용법
- 저장
@Transactional
@SpringBootTest
public class ManyToManyTest {
@Autowired FoodRepository foodRepository;
@Autowired MemberRepository memberRepository;
@Test
@Rollback(value = false)
@DisplayName("N대M 단방향 저장 테스트")
void OneWaySaveTest() {
// 음식(Food)
Food food = new Food("후라이드 치킨", 15000);
foodRepository.save(food);
// 고객(Member)1
Member member1 = new Member("Inyong");
memberRepository.save(member1);
food.addMemberList(member1);
// 고객(Member)1
Member member2 = new Member("Robert");
memberRepository.save(member2);
food.addMemberList(member2);
}
}
- 위 코드 실행 시, 적용되는 SQL은 다음과 같습니다.
- 외래 키를 받아 중간 테이블인 Orders에 INSERT SQL이 실행됩니다.
INSERT INTO FOOD (MEMBER_ID, NAME, PRICE) VALUES (NULL, "후라이드 치킨", 15000);
INSERT INTO MEMBER (NAME) VALUES ('Inyong');
INSERT INTO MEMBER (NAME) VALUES ('Robert');
INSERT INTO ORDERS (FOOD_ID, MEMBER_ID) VALUES (1, 1);
INSERT INTO ORDERS (FOOD_ID, MEMBER_ID) VALUES (1, 2);
'JPA' 카테고리의 다른 글
[JPA] 다대다 연관관계 (양방향) (0) | 2023.04.29 |
---|---|
[JPA] 일대다 연관관계 (단방향) (0) | 2023.04.29 |
[JPA] 다대일 연관관계 (양방향) (0) | 2023.04.29 |
[JPA] 일대일 연관관계 (양방향) (0) | 2023.04.29 |
[JPA] 다대일 연관관계 (단방향) (0) | 2023.04.29 |
댓글