목표
- 이 프로젝트에서
병원
은 시,구,동
엔티티를 참조한다.
- 병원 엔티티는 시도 참조하고, 구도 참조한다.
- M:N의 관계이다.
- 특정 구는 특정 시의 자식과 같다.
- ex. 서울시 - 강남구, 경기도 - 용인시 수지구

M:N 관계
테이블에서 M:N관계
- 보통 M:N 관계라 하면 커머스에서
주문
과 상품
테이블로 생각해볼수 있겠다.
- 한 상품은 여러 주문에 있을 수 있고,
- 한 주문은 여러 상품을 주문할 수 있다.
- 여기서 참조키를 어느 쪽에 줄지가 애매하다.

- RDBMS 테이블 입장에서는 하나의 레코드에서는 하나의 FK만 가질 수 있으므로 무조건 중간 테이블이 필요하다.

객체에서 @ManyToMany
- 객체 입장에서는 M:N 관계가 자연스럽게 된다.
- 연과관계의 주인은 Order쪽으로 하겠다.

@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany
@JoinTable(name = "order_item")
private List<Item> items = new ArrayList<>();
}
@Entity
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany(mappedBy= "items")
private List<Order> orders = new ArrayList<>();
}
- 이런식으로 M:N 관계를 설정해 줄 수 있다.
- 이렇게되면 DB상으로는 중간 테이블을 JPA가 CREATE문을 통해 만들게 된다.
@ManyToMany의 한계
- 조인 테이블은 일단 확장이 불가능하다.
- 비즈니스적으로 필요한 컬럼을 추가할 수 없다.
- 심지어 생성일, 수정일 같은 컬럼도 추가할 수 없다.
- 객체 입장에서는 너무 편리하지만 실무에서는 사용이 어렵다.
해결 1
- 위와 같은
주문
- 상품
의 경우 조인 테이블을 엔티티로 만들어, N:1 관계를 2개 만들면 된다.

- OrderItem.java
@Entity
public class OrderItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "order_id")
private Order order;
@ManyToOne
@JoinColumn(name = "item_id")
private Item item;
}
- 각각에 @ManyToMany 는 제거하고, 조인테이블을 엔티티로 만들어서 @ManyToOne같은 관계를 지어준다.
해결 2
- 현재 우리 프로젝트의 경우 M:N 관계이긴 하지만 중간테이블을 만들지 않고 더 괜찮은 방법을로 해결할 수 있다.
병원
이 시, 구 중에 하나만 참조하면 되는 것이다.
- 그렇다면,
시
보다는 더 상세한 구
를 참조하는 것이 나을 것이다.
- 하지만 그렇다고해도
시
와 병원
도 연관관계가 있다.
- 이때는 셀프 레퍼런스로 해결해보자.
셀프 레퍼런스
- 자기 참조
- 부모, 즉 상위레벨의 자기 자신 엔티티를 참조해서 계층적인 테이블을 만든다.

public class Sigudong {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String sigudongName;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "parent_id")
private Sigudong parent;
@OneToMany(mappedBy = "parent")
private List<Sigudong> child = new ArrayList<>();
}

@Entity
public class Hospital {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long hosId;
private String hosName;
@ManyToOne
@JoinColumn(name = "sigudong_id")
private Sigudong sigudong;
}
- 이렇게 계층적으로 셀프 참조를 하면,
병원
쪽에서는 제일 하위 레벨의 시, 구, 동
을 참조하면 해결이 된다.