스프링 부트와 JPA 활용1 - 웹 계층 개발 8

JOY·2022년 5월 16일
0
post-thumbnail

📌 스프링 부트와 JPA 활용1 - 웹 계층 개발 8

인프런 - 스프링 부트와 JPA 활용1 by 김영한 을 기반으로 작성된 글입니다.
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발


웹 계층 개발 목차

1. 홈 화면과 레이아웃

2. 회원 등록

3. 회원 목록 조회

4. 상품 등록

5. 상품 목록

6. 상품 수정

7. 변경 감지와 병합(merge)

8. 상품 주문

9. 주문 목록 검색, 취소


구현 기능

  • 홈 화면
  • 회원 기능
    • 회원 등록
    • 회원 조회
  • 상품 기능
    • 상품 등록
    • 상품 수정
    • 상품 조회
  • 주문 기능
    • 상품 주문
    • 주문내역 조회
    • 주문 취소

주문 서비스 (OrderService.java)

package jpabook.jpashop.service;

//생략

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class OrderService {

    private final OrderRepository orderRepository;
    private final MemberRepository memberRepository;
    private final ItemRepository itemRepository;

    /**
     * 주문
     */
    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());

        //주문 상품 생성 createOrderItem 생성메서드 사용
        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();
    }
    //주문 검색
    public List<Order> findOrders(OrderSearch orderSearch) {
        return orderRepository.findAllByString(orderSearch);
	}
    
}

상품 주문 컨트롤러(OrderController.java)

코드 추가

package jpabook.jpashop.controller;

//생략

import java.util.List;

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

    /**
     * 주문
     */
    @PostMapping(value = "/order")
    public String order(@RequestParam("memberId") Long memberId,
                        @RequestParam("itemId") Long itemId,
                        @RequestParam("count") int count) {

        orderService.order(memberId, itemId, count);
        return "redirect:/orders";

    }
 }

📍 설명

  • @RequestParam : form에서 submit되어 넘어온 name value를 해당 변수에 바인딩

    orderService.order(memberId, itemId, count);
    주문 정보 : 회원 아이디, 아이템 아이디, 아이템 수량

    트랜잭션 안에서 엔티티를 조회를 해야 영속 상태로 진행 된다
    그래야 정보를 변경할 때 좋다
    가급적이면 조회가 아닌 핵심비즈니스로직이 있는 경우는
    controller에서 식별자를 넘겨 처리하는 것이 좋다

상품 주문 폼 (orderForm.html)

코드는 일부만 나타내도록 하겠다

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

📍 실행 결과

주문하기주문 회원 선택상품선택

주문 목록 검색,취소 컨트롤러(OrderController.java)

코드 추가

package jpabook.jpashop.controller;

//생략

import java.util.List;

@Controller
@RequiredArgsConstructor
public class OrderController {

	//생략

    /**
     * 주문 목록 검색
     */
    @GetMapping("/orders")
    public String orderList(@ModelAttribute("orderSearch") OrderSearch orderSearch, Model model){
        List<Order> orders = orderService.findOrders(orderSearch);
        model.addAttribute("orders", orders);

        return "order/orderList";
    }

    /**
     * 주문취소
     */
    @PostMapping("/orders/{orderId}/cancel")
    public String cancelOrder(@PathVariable("orderId") Long orderId){
        orderService.cancelOrder(orderId);
        return "redirect:/orders";
    }
}

📍 설명

  • orderList()
    OrderSearch : 주문 목록을 검색하기 위한 조건

주문 목록 검색 폼 (orderList.html)

코드는 일부만 나타내도록 하겠다

<div>
        <div class="form-inline" style="display: inline;">
            <form th:object="${orderSearch}" class="form-inline">
                <div class="form-group mb-2 " style="float: left;">
                    <input type="text" th:field="*{memberName}" class="form-control-me"
                           placeholder="회원명"/>
                </div>
                <div class="form-group mx-sm-1 mb-2" style="float: left;">
                    <select th:field="*{orderStatus}" class="form-control-me">
                        <option value="">주문상태</option>
                        <option th:each=
                                        "status : ${T(jpabook.jpashop.domain.OrderStatus).values()}"
                                th:value="${status}"
                                th:text="${status}">option
                        </option>
                    </select>
                </div>
                <button type="submit" class="btn btn-primary mb-2">검색</button>
            </form>
        </div>

📍 설명 및 실행 결과

  1. 검색하고자 하는 정보를 입력하여 검색하면 submit 되어
    orderSearch를 통해 회원 이름과 주문 상태가 바인딩 된다
@Getter @Setter
public class OrderSearch {

    private String memberName; //회원 이름
    private OrderStatus orderStatus; //주문상태[ORDER, CANCEL]
}
  1. GET 방식으로 데이터를 전송하였기 때문에 URL에서 파라미터를 확인할 수 있다
    http://localhost:8080/orders?memberName=죠르디&orderStatus=ORDER

  2. 주문 상태가 ORDER 라면, CANCEL 버튼을 나타내도록 했다

📍 실행 결과

  • 회원 목록
  • 상품 목록
  • 상품 주문
  1. 상품명 : JPA , 주문 수량 : 2

  2. 검색
    회원명 : 죠르디 , 주문 상태 : ORDER

  3. 재고 수량 확인
    10개였던 재고 수량이 2개 주문으로 인해 8개가 된 것 확인

  4. 주문 상태 : CANCEL 검색
    취소된 주문건이 없기 때문에 검색결과가 없다

  • 주문 취소
  1. 회원명 : 죠르디
    주문 상태 변한 것 확인

  2. 주문 상태 : ORDER 검색
    주문건을 취소하였기 때문에 검색결과가 없다

  3. 재고 수량 확인
    8개였던 재고 수량이 2개 주문 취소로 인해 10개가 된 것 확인

❗ 오류 1

주문 시 발생한 오류

WARN 7984 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'item' for method parameter type Long is not present]

@PostMapping("/order")
    public String order(@RequestParam("memberId") Long memberId,
                        @RequestParam("item") Long itemId,
                        @RequestParam("count") int count){

        orderService.order(memberId, itemId, count);
        return "redirect:/orders";
    }

💡 원인
부분에서 상품명의 name 은 itemId 인데 @RequestParam("item") 에서
item으로 파라미터를 잘못 입력했다. 타입이 맞지 않았던 것

💡 해결
@RequestParam의 파라미터를 itemId로 변경

@RequestParam("itemId") Long itemId
profile
Just Do IT ------- 🏃‍♀️

0개의 댓글