spring

M:N 다대다 연관 관계

짱쭈니어 2025. 2. 10. 14:54

 

 관계형 DB 에서 M:N 연관관계

    •  비즈니스 서비스를 DB 를 모델링 하는 과정에서 다대다 관계가 나올 수 있다.
      • 1개의 주문은 N개의 상품을 주문한다.
      • 1개의 상품은 M개 주문에 포함될 수 있다.
      • 이렇게 되면 관계형DB 입장에서는 관계를 표시할 수가 없다.
        • 하나의 레코드에서 하나의 FK 만 가져야 하기 때문이다.
        • “콩나물” 상품을 M개 주문했다면 상품테이블에 주문 외래키로 뭐를 가져야할지?
        • 1번 주문에 여러개 상품을 주문했다면, 주문테이블에 상품 외래키로 뭐를 가져야할지?
          • 즉 서로의 외래키가 애매해진다..

주문과 상품의 다대다 관계

 

 b. 다대다 연관관계 해소를 위한 중간테이블 필요

  • 하나의 레코드에서 한 개의 FK 명시를 위해서는 중간테이블이 필요하다
    • 중간테이블을 만들어서, 1:N 관계를 2개를 만든다.
    • 1개 주문에 N개의 주문 상품을, 1개의 상품은 N개의 주문 상품을 바라보게 만든다.

 

 c. 사용하다가 추후 다대다 관계가 생겼다면? 

  • 기존
    • a, b 테이블 기존에는 두 테이블간의 관계정립이 필요하지 않은 채, 따로 놀고 있는 테이블
      • 새로 생겨야하는 기능으로, 두 테이블간의 관계 정립이 필요해짐 
  • 그러나, M:N 관계이다보니, 외래키로 연관관계 매핑이 안되어서 원하는 값을 찾을 수가 없없다
    • 중간 테이블을 생성하여서 두 테이블간의 연관관계를 1:N 관계 2개로 풀기로 하였다.


d. 다대다 관계 해소를 위한 중간테이블 생성 방법

  • 새로운 테이블을 기존의  테이블들의 PK 를 외래키로 가져야한다.
// 가상의 예를 들었습니다. 
create table goods_location
(
    goods_id          bigint unsigned        not null ,
    location_seq      int unsigned           not null comment '순번',
   // ... 내용 생략
    primary key (goods_id, location_seq)
)comment '상품_위치';

 

 

// 가상의 예를 들었습니다.
create table location_info
(
    location_id    varchar(30)                  not null ,
    label_no        char(3) charset utf8mb4      not null ,
     // ... 내용 생략
    primary key (location_id, label_no)
);

 

  • 이렇게 테이블들이 있을때, 새로운 테이블을 위 테이블들과 연관관계를 맺어야한다.
    • 그러기 위해, 새로운 테이블은 위 테이블들의 PK 를 외래키로 가져야한다.
create table goods_location_info
(
   goods_location_info_id bigint unsigned not null AUTO_INCREMENT PRIMARY KEY
    
    goods_id        bigint unsigned       not null ,
    location_seq    int unsigned          not null comment '순번' ,
    
    location_id     varchar(20)   not null ,
    label_no        char(3)       not null ,

    foreign key (goods_id,location_seq) references 
    goods_location (goods_id, location_seq),
    
    foreign key (location_id, label_no) references 
    location_info (location_id, label_no)
) ;