Spring/JPA활용 SpringBoot 기본

MVC 계층 개발 3. 주문, 주문 취소, redirect 주의, Transaction 주의

Per ardua ad astra ! 2021. 8. 25. 22:26

OrderController

@Controller
@RequiredArgsConstructor
public class OrderController {

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

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

        return "orders/orderForm";
    }

    @PostMapping("/order")
    public String itemOrder(@RequestParam(value = "memberId") Long memberId,
                            @RequestParam(value = "itemId") Long itemId,
                            @RequestParam(value = "count") int count) {
        orderService.order(memberId, itemId, count);

        return "redirect:/orders";
    }

    @GetMapping("/orders")
    public String orderList(OrderSearch orderSearch, Model model) {
        List<Order> orders = orderService.findOrders(orderSearch);
        model.addAttribute("orders", orders);

        return "orders/orderList";
    }

    @PostMapping("/orders/{id}/cancel")
    public String orderListUpdated(@PathVariable("id") Long orderId){
        orderService.cancelOrder(orderId);
        return "redirect:/orders";
    }

}

 

배운내용은 거의 중복이라 돌아가는 매커니즘만 확인하면 될 것 같다. 

 

  • 아이템을 주문하기 위해서
    model을 통해 뷰에 멤버들과 아이템 데이터들을 전달한다. 사용자는 response된 화면에서 주문할 사용자 정보와 아이템 정보를 선택할 수 있고 submit 버튼을 누를 것이다. -> Post

    뷰에서 전달한 parameter 값들을 @RequestParam 을 이용해서데이터를 받는다. oderService를 통해 아이템 주문 메소드은 order(memberId, itemId, count)를 진행한다. 

  • 주문이 완료되면 바로 주문 조회 창으로 이동해야 한다. 이때 주의할점은 "redirect:/orders"를 통하여 페이지 이동을 해야된다는 것이다. "orders/orderList" 로 전달하게 될경우에는 orderList.html의 form 태그의 커맨드 객체인 orderSearch에 대한 파라미터 값이 없어서 오류가 발생한다. 
    오류 발생 화면
    model에 대한 정보없이 바로 http를 통해 접근할 때는 redirect를 꼭 이용하자.

  • orderSearch를 통해 주문상품에 대한 데이터가 조회되면 이를 취소할 수 있다. CANCEL버튼을 누르면 최소되는데 이때 "/orders/{id}/cancel" 링크로 가게되고 id는 @PathVariable을 통해 접근하여 order를 취소 할 수 있다. 

    정상적인 코드는 
    @PostMapping("/orders/{id}/cancel") 
    public String orderListUpdated(@PathVariable("id") Long orderId){ 
    	orderService.cancelOrder(orderId); 
        return "redirect:/orders";
    }
     이지만,, 혼자 코드를 작성할 때 

    내가 작성한 잘못된 코드
        @PostMapping("/orders/{id}/cancel")
        public String orderListUpdated(@PathVariable("id") Long orderId){
            Order order = orderService.findOne(orderId);
            order.cancelOrder();
            return "redirect:/orders";
        }​

    이렇게 작성했었다... 위의 cancelOrder()함수가 아래의 
    코드인점을 이루어 봤을 때 별로 다를 것이 없어 보일 수 있다. ....

    하지만 !! 이것은 나의 치명적인 판단 착오이다. 내가 잘못 작성한 코드는 조회할 때만 service를 이용하여 트랜잭션에 접근하고 데이터를 가져오지만, Transcation을 이용하여 DB에 직접 접근한 것도 아니고, 영속성 컨택스트의 값에 접근했다 하더라고 flush를 하지 않기 때문에 바로 변경된 데이터 반영이 불가하다. 즉, order.cancelOrder()를 실행할 때는 엔티티 계층에서 값을 변화 시켜도 Transaction에 의해 데이터가 변경된것이 아니기 때문에 클라이언트는 바로바로 변경된 데이터를 확인하지 못한다. 

    반면 정상적인 코드에서 oderService.cancelOrder(orderId)로 할 때는 이 함수 전체의 작업처리가 하나의 Transaction 안에서 함께 처리되고 데이터를 조회하고 변경하고 함수가 처리가 끝이되면 변경된 것이 자동으로 반영되어 client로 넘어가므로 그런 것 같다. 


    SpringBoot-Basic-main.zip
    1.40MB
  • public void cancelOrder(Long orderId){ // CANCEL 버튼을 누르면 id만 넘어온다. // 주문 엔티티 조회 Order order = orderRepository.findOne(orderId); // 주문 취소 order.cancelOrder(); }​

 

 

이 게시물은 '실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발' 강의를 수강하고 정리한 내용임을 밝힙니다.

출처: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-%ED%99%9C%EC%9A%A9-1/

 

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발 - 인프런 | 강의

실무에 가까운 예제로, 스프링 부트와 JPA를 활용해서 웹 애플리케이션을 설계하고 개발합니다. 이 과정을 통해 스프링 부트와 JPA를 실무에서 어떻게 활용해야 하는지 이해할 수 있습니다., 본

www.inflearn.com