스프링데이터 + JPA/웹 애플리케이션 개발

26. 상품 주문

sdafdq 2023. 11. 11. 23:33

일반적인 예제는 아니다.

상품 주문할 멤버를 선택하고, 

주문할 상품을 선택하고 수량을 입력하는 그런 식이다.

 

보통은 로그인 하고, 세션을 통해 서버의 세션저장소에서 서버가 어떤 member인지 계속 가져오고,

그 member가 상품을 주문하고 그런 식임.

지금은 좀 관리자가 상품 주문 시켜주는 느낌임.

 

@Controller
@RequiredArgsConstructor
public class OrderController {
    private final OrderService orderService;
    private final MemberService memberService;
    private final ItemService itemService;

    @GetMapping("/order")
    public String createForm(Model model){
        List<Member> members = memberService.findMembers();
        List<Item> items = itemService.findItems();

        model.addAttribute("members", members);
        model.addAttribute("items", items);

        return "order/orderForm";
    }
}

그래서 그냥 이렇게 다 불러와 orderForm에 뿌려줄 것이다.

 

@PostMapping("/order")
public String order(@RequestParam("memberId") Long memberId,
                    @RequestParam("itemId")Long itemId,
                    @RequestParam("count") int count){
    orderService.order(memberId, itemId, count);
    return "redirect:/orders";
}

memberId, itemId, count를 받는다.

그 다음 orderService에서 order한다.

그 다음 새로고침 시 똑같은 걸 재 요청하게 되면 성가시니까 redirect 시킨다.

 

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/header :: header" />
<body>
<div class="container">
    <div th:replace="fragments/bodyHeader :: bodyHeader"/>
    <form role="form" action="/order" method="post">
        <div class="form-group">
            <label for="member">주문회원</label>
            <select name="memberId" id="member" class="form-control">
                <option value="">회원선택</option>
                <option th:each="member : ${members}"
                        th:value="${member.id}"
                        th:text="${member.name}" />
            </select>
        </div>
        <div class="form-group">
            <label for="item">상품명</label>
            <select name="itemId" id="item" class="form-control">
                <option value="">상품선택</option>
                <option th:each="item : ${items}"
                        th:value="${item.id}"
                        th:text="${item.name}" />
            </select>
        </div>
        <div class="form-group">
            <label for="count">주문수량</label>
            <input type="number" name="count" class="form-control" id="count"
                   placeholder="주문 수량을 입력하세요">
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
    <br/>
    <div th:replace="fragments/footer :: footer" />
</div> <!-- /container -->
</body>
</html>

"memberId" 등은 저기 태그의 name임. 그것의 value가 값이 되는거.

 

order는

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();
}

member, item 찾고,

주소 설정하고,(이번에는 간단하게 하기 위해 그냥 member의 주소로 함)

 

orderItem을 생성해 준다음에,

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;
}

 

order도 생성해 주고,

public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems){
    Order order = new Order();
    order.changeMember(member);
    order.changeDelivery(delivery);
    for (OrderItem orderItem : orderItems) {
        order.addOrderItem(orderItem);
    }
    order.setStatus(OrderStatus.ORDER);
    order.setOrderDate(LocalDateTime.now());
    return order;
}

 

save 해 주면 된다.

 

 

컨트롤러에서는 왠만하면 엔티티로써 넘기지 말고 식별자로 넘기고,

엔티티는 트랜잭션이랑 같은 주기에 있는게 훨씬 관리하기 편하다. (영속성 컨텍스트)

 

영속성 컨텍스트는 트랜잭션 단위이기 때문에,

컨트롤러에서 조회해온다음에 값을 바꿔봤자, 서비스에서 다른 트랜잭션이면 반영이 안된다.

 

트랜잭션이랑 영속성 컨텍스트의 생명주기는 같다.

다른 트랜잭션에서 넘어온 엔티티는 (트랜잭션 전파가 있지 않는 한) 이번의 트랜잭션과 관계없는 엔티티이다.

 

 

 

 

 

'스프링데이터 + JPA > 웹 애플리케이션 개발' 카테고리의 다른 글

27. 주문 목록 검색, 취소  (0) 2023.11.12
25. 변경감지와 병합  (0) 2023.11.11
24. 상품 수정  (0) 2023.11.10
23. 상품 등록  (0) 2023.11.10
22. 회원 목록 조회  (0) 2023.11.10