관리 메뉴

Mini

상품주문 // 컨트롤러 : 인자넘기기만 하라 / 처리는 서비스계층에서 본문

Java/Spring-app

상품주문 // 컨트롤러 : 인자넘기기만 하라 / 처리는 서비스계층에서

Mini_96 2023. 7. 30. 16:27

* OrderController

package jpabook.jpashop.controller;

import jpabook.jpashop.domain.Member;
import jpabook.jpashop.domain.OrderService;
import jpabook.jpashop.domain.item.Item;
import jpabook.jpashop.repository.OrderSearch;
import jpabook.jpashop.service.ItemService;
import jpabook.jpashop.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Controller
@RequiredArgsConstructor
public class OrderController {

    private final OrderService orderService;
    private final MemberService memberService;
    private final ItemService itemService;

    @GetMapping(value = "/order")
    public String createForm(Model model){
        //고객정보, 상품정보를 model에 담아 뷰에넘긴다.

        List<Member> members = memberService.findMembers();
        List<Item> items = itemService.findItems();

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

        return "order/orderForm";

    }

    //"제출" 누르면 /order URL을 POST방식으로 호출
    //고객아이디, 아이템아이디, 수량 받아서 함수내용실행
    @PostMapping(value = "/order")
    public String order(@RequestParam("memberId") Long memberId,
                        @RequestParam("itemId") Long itemId,
                        @RequestParam("count") int count){
        orderService.order(memberId, itemId, count);
        //컨트롤러에서 memberId 등 엔티티를 찾고 수정해도 되지않나요?
        // 단점 : 트랜잭션이 아니기떄문에 영속성이아님. DB반영이안됨.
        //-> 컨트롤러에서는 넘기기만하고 서비스계층에서 처리하라.
        return "redirect:/orders";
    }
}
//컨트롤러에서 memberId 등 엔티티를 찾고 수정해도 되지않나요?
// 단점 : 트랜잭션이 아니기떄문에 영속성이아님. DB반영이안됨.
//-> 컨트롤러에서는 넘기기만하고 서비스계층에서 처리하라.

* 서비스계층(여기서 직접조회및 처리)

장점 : 영속성컨텍스트임 -> JPA가 관리해줌.

 @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 기본생성자에 Protected 걸어
        해결2 : 롬복 : @NoArgsConstructor(access= AccessLevel.PROTECTED)
         */
        Order order=Order.createOrder(member,delivery,orderItem);
        //new Order() XXX

        //주문 저장
        /* CASCADE
        문제 : delivery, orderitem은 persist안함?
        해결 : order클래스에 cascade걸려잇는멤버 => order persist -> 자동persist
        문제1 : orderitem, delivery을 order에서만 참조하는 경우에만 사용할것!
        문제2 : delivery, orderitem을 여러군데서 사용하는경우?
        해결 : 별도의 repository => 각각 persist
         */
        orderRepository.save(order);

        return order.getId();
    }

*HTML

<!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>