Spring/Sample Project

[Spring Boot] 기본 CRUD 구현 - 2 (Entity 관계 설정)

shininghyunho 2023. 10. 4. 18:18

기본 컨셉은 쇼핑몰이다.

유저가 주문을 하고 확인하는 기능을 만들예정이다.

 

기본적인 시나리오는 다음과 같다.

1. 유저가 상품을 주문할 수 있다.

2. 주문목록은 여러 목록과 갯수가 있다. ex) 사과 3개, 바나나 2개, 포도 5개

3. 유저가 주문 목록을 확인할 수 있다.


Entity 관계 설정

Entity는 기본적으로 User와 Item 이 있다.

 

근데 유저 A가 사과를 주문할수도 있고 유저 B가 사과를 주문할수도 있다.

반대로 유저 A가 사과, 바나나, 포도도 구매할 수 있다.

 

그래서 유저와 아이템은 N:M 의 다대다 관계가 생성된다.

하지만 테이블 설계를 User 와 Item으로만 설정한다면 주문 목록에 대한 속성값 추가가 어렵게된다.


그래서 주문 테이블을 추가하기로했다.

하지만 여전히 주문과 아이템이 다대다 관계이다.

ex) 1개의 주문에는 여러개의 아이템이 들어갈수있는데, 1번 주문과 2번 주문의 공통된 아이템이 들어갈수있다.


김영한의 JPA 북에서처럼 다음과 같이 설정할 수도 있다.

그러나 1개의 공통된 주문목록을 보고 싶은데 그림 6.14처럼 설계한다면 중복이 계속 생긴다.

 

ex) Id=1 유저가 사과 3개, 바나나 2개, 포도 5개를 주문한다면 Order 테이블은 다음과 같을것이다.

 

<주문 테이블>

  유저 ID 아이템 ID 갯수 주문 날짜 주문 요구 사항 배달 현황
1번 주문 1 1 3 2023.10.04 빨리 갖다주세요 준비중
2번 주문 1 2 2 2023.10.04 빨리 갖다주세요 준비중
3번 주문 1 3 5 2023.10.04 빨리 갖다주세요 준비중

 


그래서 주문과 주문한 아이템을 다시 분리해야했다.

 

최종적으로는 다음과 같이 분리했다.

<주문 테이블>

  유저 ID 주문_아이템 ID 주문 날짜 주문 요구 사항 배달 현황
1번 주문 1 1 2023.10.04 빨리 갖다주세요 준비중
2번 주문 1 2 2023.10.04 빨리 갖다주세요 준비중
3번 주문 1 3 2023.10.04 빨리 갖다주세요 준비중

 

<주문 아이템 테이블>

  아이템 ID 갯수
1번 주문 아이템 1 3
2번 주문 아이템 2 2
3번 주문 아이템 3 5

 


실제 구현 코드는 다음과 같다.

(관계 설정만 해놓은 상태)

// User
@Entity
class User(
    var email: String,
    var password: String,

    @OneToMany(mappedBy = "user")
    val orders: MutableSet<Order> = hashSetOf(),
) {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0
}

// Item
@Entity
class Item(
    var price: Long,
    var name: String,
    var quantity: Int,
) {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0
}

// Order
@Table(name = "ORDERS")
@Entity
class Order(
    @ManyToOne
    @JoinColumn(name = "user_id")
    val user: User,

    @OneToMany(mappedBy = "order")
    val orderItems: MutableSet<OrderItem> = hashSetOf(),
) {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0
}

// OrderItem
@Entity
class OrderItem(
    @ManyToOne
    @JoinColumn(name = "order_id")
    val order: Order,

    @ManyToOne
    @JoinColumn(name = "item_id")
    val item: Item,
    
    val count: Int,
) {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0
}