인프런 - 스프링 부트와 JPA 활용1 by 김영한 을 기반으로 작성된 글입니다.
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
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);
}
}
코드 추가
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에서 식별자를 넘겨 처리하는 것이 좋다
코드는 일부만 나타내도록 하겠다
<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>
주문하기 | 주문 회원 선택 | 상품선택 |
---|---|---|
코드 추가
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";
}
}
📍 설명
코드는 일부만 나타내도록 하겠다
<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>
📍 설명 및 실행 결과
@Getter @Setter
public class OrderSearch {
private String memberName; //회원 이름
private OrderStatus orderStatus; //주문상태[ORDER, CANCEL]
}
GET 방식으로 데이터를 전송하였기 때문에 URL에서 파라미터를 확인할 수 있다
http://localhost:8080/orders?memberName=죠르디&orderStatus=ORDER
주문 상태가 ORDER 라면, CANCEL 버튼을 나타내도록 했다
상품명 : JPA , 주문 수량 : 2
검색
회원명 : 죠르디 , 주문 상태 : ORDER
재고 수량 확인
10개였던 재고 수량이 2개 주문으로 인해 8개가 된 것 확인
주문 상태 : CANCEL 검색
취소된 주문건이 없기 때문에 검색결과가 없다
회원명 : 죠르디
주문 상태 변한 것 확인
주문 상태 : ORDER 검색
주문건을 취소하였기 때문에 검색결과가 없다
재고 수량 확인
8개였던 재고 수량이 2개 주문 취소로 인해 10개가 된 것 확인
주문 시 발생한 오류
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