Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- 리액트 네이티브 프로젝트 생성
- 팀플회고
- 데베
- 네트워크
- 모두의네트워크
- HTTP
- 깃허브 로그인
- 정리
- 데이터베이스
- 리액트 네이티브 시작하기
- 모두의 네트워크
- 백준 4358번
- 깃허브 토큰 인증
- React Native
- 백준 5525번
- 모두를위한딥러닝
- 머신러닝
- 백준 4949번
- 문자열
- 깃 연동
- 백준
- 지네릭스
- 모두를 위한 딥러닝
- 백준 4358 자바
- 리액트 네이티브
- 딥러닝
- 스터디
- 자바
- SQL
- 깃 터미널 연동
Archives
- Today
- Total
솜이의 데브로그
[Spring Boot] 주문 도메인 개발(1) 본문
Reference : Inflearn 실전 스프링부트와 JPA 활용 (김영한님 강의)
상품 주문, 주문 내역 조회, 주문 취소 기능을 포함한 주문 도메인을 개발해보자.
주문 엔티티, 주문 상품 엔티티 개발
domain/Order.java
- 생성 메서드 createOrder() : 주문 엔티티 생성할 때 사용.
- 생성 메서드에서 다 set해서 완결시켜버림.
- 주문 취소 cancel() : 이미 배송 완료한 상품이면 주문 취소하지 못하도록 예외
- 비즈니스 로직에 대한 check logic이 엔티티 안에 있다.
- 상태 바꾸고 루프 돌면서 아이템의 재고 수정.
- 전체 주문 가격 조회
- 개별의 주문 가격과 수량을 곱해서 나온 결과를 더해서 반환.
//--생성 메서드==//
public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems){
Order order= new Order();
order.setMember(member);
order.setDelivery(delivery);
for(OrderItem orderItem: orderItems){
order.addOrderItem(orderItem);
}
order.setStatus(OrderStatus.ORDER);
order.setOrderDate(LocalDateTime.now());
return order;
}
//==비즈니스 로직==//
/**
* 주문 취소
*/
public void cancel(){
if(delivery.getStatus() == DeliveryStatus.COMP){
throw new IllegalStateException("이미 배송완료된 상품은 취소가 불가능합니다.");
}
this.setStatus(OrderStatus.CANCEL);
for (OrderItem orderItem : orderItems){
orderItem.cancel();
}
}
//==조회 로직==//
/**
* 전체 주문 가격 조회
*/
public int getTotalPrice(){
int totalPrice = 0;
for(OrderItem orderItem : orderItems){
totalPrice += orderItem.getTotalPrice();
}
return totalPrice;
}
domain/OrderItem.java
- cancel 메서드 추가 (비즈니스 로직) : 취소한 수량만큼 상품의 재고를 증가한다.
- 생성 메서드 createOrderItem() : 각 정보를 사용해서 주문 상품 엔티티 생성, item.removeStock() 호출해서 주문한 수량만큼 상품의 재고는 차감한다.
- 주문 가격 조회 : 주문가격 * 수량 값을 반환
//==생성 메서드==//
public static OrderItem createOrderItem(Item item, int orderPrice, int count){
OrderItem orderItem = new OrderItem();
orderItem.setItem(item);
orderItem.setOrderPrice(orderPrice);
orderItem.setCount(count);
item.removeStock(count);
return orderItem;
}
//==비즈니스 로직==//
public void cancel() {
getItem().addStock(count);
}
//==조회 로직==//
/**
* 주문 상품 전체 가격 조회
*/
public int getTotalPrice() {
return getOrderPrice() * getCount();
}
주문 리포지토리 개발
repository/OrderRepository
package jpabook.jpashop.repository;
import jpabook.jpashop.domain.Order;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
@Repository
@RequiredArgsConstructor
public class OrderRepository {
private final EntityManager em;
public void save(Order order){
em.persist(order);
}
public Order findOne(Long id){
return em.find(Order.class, id);
}
// public List<Order> findAll(OrderSearch orderSearch){}
}
- 엔티티를 저장하고 검색
주문 서비스 개발
service/OrderService.java
- 주문을 데이터로 변환하므로 @Transactional 필요
- order가 persist 될 때 castcade 걸린것 다 실행해서 orderItem과 delivery가 다 실행된다.
- protected 통해서 생성자 다른 형태로 만드는 것 막을 수 있다. lombok으로도 막을 수 있음.
- @NoArgsConstructor(access=AccessLevel.PROTECTED)
- 코드를 제약하는 스타일로 짜는 것이 설계, 유지 보수에 좋다!!!
- JPA의 장점 : 변경한 데이터를 바깥에서 업데이트 쿼리를 짜서 날릴 필요가 없다.
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class OrderService {
private final OrderRepository orderRepository;
private final MemberRepository memberRepository;
private final ItemRepository itemRepository;
/**
* 주문
*/
@Transactional
public Long order(Long memberId, Long itemId, int count){
//엔티티 조회
Member member = memberRepository.findOne(memberId);
Item item = itemRepository.findOne(itemId);
//배송정보 생성성
Delivery delivery = new Delivery();
delivery.setAddress(member.getAddress());
//주문상품 생성
OrderItem orderItem = OrderItem.createOrderItem(item, item.getPrice(), count);
//주문 생성
Order order = Order.createOrder(member, delivery, orderItem);
//주문 저장
orderRepository.save(order);
return order.getId();
}
/**
* 주문 취소
*/
@Transactional
public void cancelOrder(Long orderId){
//주문 엔티티 조회
Order order = orderRepository.findOne(orderId);
//주문 취소
order.cancel();
}
}
★ 주문 서비스의 주문과 취소 메서드는 비즈니스 로직이 대부분 엔티티에 있다.
서비스 계층은 단순히 엔티티에 필요한 요청을 위임하는 역할만 수행한다. 이런 스타일을 '도메인 모델 패턴'이라고 한다. JPA나 ORM 쓰면 이런식으로 도메인 안에 로직을 다 넣는다.
반대로 엔티티에 로직이 별로 없고 서비스 계층에서 대부분의 비즈니스 로직을 처리하는 것을 '트랜잭션 스크립트 패턴'이라고 한다.
어떤 쪽이 더 유지 보수하기 쉬운지 고민해서 채택해서 사용하도록 하자~
한 트랜잭션 안에서도 양립 가능!
'dev > Spring Boot' 카테고리의 다른 글
[SpringBoot] 웹 계층 개발(1) (0) | 2022.03.25 |
---|---|
[Spring Boot] 주문 도메인 개발(2) (0) | 2021.12.03 |
[Spring Boot] 상품 도메인 개발 (0) | 2021.11.15 |
[Spring Boot] 회원 도메인 개발 (0) | 2021.11.10 |
[Spring Boot] 엔티티 설계 시 주의점 (0) | 2021.10.09 |