[스프링부트JPA] 쇼핑몰 다대일 단방향 매핑하기

JEONG SUJIN·2023년 2월 5일
0

장바구니에는 고객이 관심이 있거나 나중에 사려는 상품들을 담아둘 건데
하나의 장바구니에는 여러개의 상품들이 들어갈 수 있다.
또한 같은 상품을 여러개 주문할 수도 있으므로 몇개를 담아줄 것인지도 설정해줘야 한다.

CartItem.java

@Entity
@Getter
@Setter
@Table(name="cart_item")
public class CartItem {
	@Id
	@GeneratedValue
	@Column(name="cart_item_id")
	private Long id;
	
    //하나의 장바구니에는 여러개의 상품을 담을 수 있으므로 @ManyToOne으로 다대일 관계맵핑 설정  
	@ManyToOne
	@JoinColumn(name="cart_id")
	private Cart cart;
    
    
	/*
	 * 장바구니에 담을 상품의 정보를 알아야 하므로 상품 엔티티를 매핑해준다. 
	 * 하나의 상품은 여러개의 장바구니의 장바구니에 상품으르 담길 수 있으므로 
	 * 마찬가지로 @ManyToOne 어노테이션으로 다대일관계로 매핑 
	 * */
	@ManyToOne
	@JoinColumn(name="item_id")
	private Item item;
    
    private int count; //같은상품을 몇개 담을지 저장

}

서버를 시작하고 콘솔창에 엔티티에 설정해놓은거 joinColumn칼럼명이 제대로 추가된걸 확인할 수 있다.

다대일/일대다 양방향 매핑하기

양방향 매핑이란 단방향 매핑이 2개있다고 생각하면된다.
위에 예제에서 현재는 장바구니 상품 엔티티가 장바구니를 참조하는 단방향 매핑
장바구니 엔티티에 장바구니 상품 엔티티를 일대다 관계로 매핑을 해준다면 양방향 매핑이되는 것.

주문과 주문상품의 매핑을 통해 양방향 매핑을 이해해보자

OrderStatus.java

package com.shopping.study.constant 에 OrderStatus 생성

public enum OrderStatus {
ORDER, CANCEL
}
UsersOrder
user_id(PK)order_id(PK)
nameuser_id
emailorder_date
passwordorder_status
address

Order.java

  • 한명의 회원은 여러 번 주문을 할수 있으므로 주문 엔티티 기준에서 다대일 단뱡항 매핑
@Entity
@Table(name="orders")
@Getter
@Setter
public class Order {

	@Id
	@GeneratedValue
	@Column(name="order_id")
	private Long id;
	
	//한명의 회원은 여러분 주문을 할수 있으므로 다대일 단방향으로 매핑
	@ManyToOne
	@JoinColumn(name="user_id")
	private Users users;
	
	private LocalDateTime orderDate;//주문일
	
	@Enumerated(EnumType.STRING)
	private OrderStatus orderStatus; //주문상태
	
	private LocalDateTime regTime;
	private LocalDateTime updateTime;
}

OrderItem.java

  • 하나의 상품은 여러 주문 상품으로 들어갈 수 있으므로 주문상품 기준으로 다대일 단방향 매핑을 설정
  • 한 번의 주문에 여러개의 상품을 주문할 수 있으므로 주문상품 엔티티와 주문엔티티를 다대일 단방향 매핑
@Entity
@Getter
@Setter
public class OrderItem {

	@Id
	@GeneratedValue
	@Column(name="order_item_id")
	private Long id; 
	
	@ManyToOne
	@JoinColumn(name="item_id")
	private Item item;
	
	@ManyToOne
	@JoinColumn(name="order_id")
	private Order order;
	
	private int orderPrice;
	private int count;
	private LocalDateTime regTime;
	private LocalDateTime updateTime;
}

다대일과 일대다는 반대관계라고 생각하면된다. 주문상품엔티티 기준에서 다대일 매핑이었으므로 주문 엔티티 기준에서는 주문상품엔티티와 일대다 관계로 매핑하면 된다.

또한 양방향 매핑에서는 '연관관계 주인'을 설정해야 한다.

ORDERS와 ORDER_ITEM 테이블에을 ORDER_ID를 외래키로 조인하면 주문에 속한 상품이 어떤 상품들이 있는지 알수 있고, 주문상품은 어떤 주문에 속하는지를 알 수 있습니다. 즉, 테이블은 외래키 하나로 양방향 조회가 가능하다.

하지만 엔티티는 테이블과 다르다.
엔티티를 양방향 연관관계로 설정하면 객체의 참조는 둘인데 외래키는 하나이므로 둘 중 누가 외래키를 관리할지를 정해야 한다.

  • 연관 관계의 주인은 외래키가 있는곳으로 설정
  • 연관 관계의 주인이 외래키를 관리(등록,수정,삭제)
  • 주인이 아닌 쪽은 연관 관계 매핑 시 mappedBy 속성의 값으로 연관 관계의 주인을 설정
  • 주인이 아닌 쪽은 읽기만 가능

연관관계의 주인 설정을 자세히 봐야 한다.
Order엔티티에 OrderItem과 연관 관계 매핑을 추가.
OrderItem엔티티에서 이미 다대일 단방향 매핑을 했으므로 양방향 매핑이 된다.

Order.java

  • OrderItem에서 이미 @ManyToOne 단방향으로 설정했기 때문에 여기서는 OneToMany로 양방향 매핑이 된다.

  • 주문상품 엔티티와 일대다 매핑. 외래키가 order_item테이블에 있으므로 연관 관계 주인은 OrderItem엔티티이다.
    Order엔티티가 주인이 아니므로 "mappedBy"속성으로 연관 관계의 주인을 설정
    속성의 값으로 order를 적어준 이유는 OrderItem에 있는 Order에 의해 관리된다는 의미

  • 하나의 주문이 여러개의 주문 상품을 가지므로 List자료형을 사용해서 매핑

@OneToMany(mappedBy="order")
	private List<OrderItem> orderItems = new ArrayList<>();

무조건 양향뱡으로 연관관계를 매핑하면 해당 엔티티는 엄청나게 많은 테이블과 연관관계를 맺게 되고 엔티티 클래스 자체가 복잡해지기 때문에 연관관계 단뱡향 매핑으로 설계 후 나중에 필요할 경우 양방향 매핑을 추가하는것을 권장


다대다 매핑

다대다매핑을 사용하지 않는 매핑 관계. 관게형 데이터베이스는 정규화된 테이블 2개로 다대다를 표현할 수 가 없다.
연결테이블을 생성해서 다대다 관계를 일대다, 다대일 관계로 풀어낸다

객체는 테이블과 다르게 컬렉션을 사용해서 다대다 관계를 표현할 수 있다.
users엔티티는 item을 리스트 형태로 가질 수 있으며, item 엔티티도 users를 리스트로 가질 수 있다.

profile
기록하기

0개의 댓글