📍Order.java
생성 메서드 : 앞으로 생성할 때 이 아이만 변경하면 됨
public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems){
Order order = new Order();
order.setMember(member);
order.setDelivery(delivery);
for(OrderItem orderItem : orderItems){
order.addOrderItem(orderItem);
}
order.setStatus(OrderStatus.ORDER);
order.setOrderDate(LocalDateTime.now());
return order;
}
📍OrderItem.java
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.java-주문 취소
public void cancel(){
if(delivery.getStatus()==DeliveryStatus.COMP)
{
throw new IllegalStateException("이미 배송완료로 취소 불가");}
this.setStatus(OrderStatus.CANCEL);
for(OrderItem orderItem : orderItems){
orderItem.cancel();
}
}
📍OrderItem.java
재고 상태를 원상복구 해줘야 함
public void cancel() {
getItem().addStock(count);
}
📍Order.java - 전체 주문 가격 조회
public int getTotalPrice(){
int totalPrice = 0;
for(OrderItem orderItem : orderItems){
totalPrice += orderItem.getTotalPrice()
}
return totalPrice;
}
📍OrderItem.java - 주문 상품 전체 가격 조회
public int getTotalPrice(){
return getOrderPrice() * getCount();
}
/** 주문 */
// 엔티티 조회
Member member = memberRepository.findOne(memberId);
Item item = itemRepository.findOne(itemId);
// 배송정보 조회
Delivery delivery = new Delivery();
delivery.setAddress(member.getAddress());
delivery.setStatus(DeliveryStatus.READY);
//주문상품 생성
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.findAll(orderSearch);
}
*/
주문 저장 orderRepository.save(order);
: Order.java에서 orderItem을 CascadeType.All 옵션 설정으로
오더와 딜리버리가 같이 persist된다.
private Member createMember() {
Member member = new Member();
member.setName("회원1");
member.setAddress(new Address());
em.persist(member);
return member;
}
private Book createBook(String name, int price, int stockQuantity) {
Book book = new Book();
book.setName(name);
book.setStockQuantity(stockQuantity);
book.setPrice(price);
em.persist(book);
return book;
}
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class OrderServiceTest {
@PersistenceContext
EntityManager em;
@Autowired OrderService orderService;
@Autowired OrderRepository orderRepository;
@Test
public void 상품주문() throws Exception {
//Given
Member member = createMember();
Item item = createBook("시골 JPA", 10000, 10);
int orderCount = 2;
//When
Long orderId = orderService.order(member.getId(), item.getId(), orderCount);
//Then
Order getOrder = orderRepository.findOne(orderId);
assertEquals("상품 주문시 상태는 ORDER",OrderStatus.ORDER, getOrder.getStatus());
assertEquals("주문한 상품 종류 수가 정확해야 한다.",1, getOrder.getOrderItems().size());
assertEquals("주문 가격은 가격 * 수량이다.", 10000 * 2, getOrder.getTotalPrice());
assertEquals("주문 수량만큼 재고가 줄어야 한다.",8, item.getStockQuantity());
}
@Test(expected = NotEnoughStockException.class)
public void 상품주문_재고수량초과() throws Exception {
//Given
Member member = createMember();
Item item = createBook("시골 JPA", 10000, 10);
int orderCount = 11; //재고보다 많은 수량
//When
orderService.order(member.getId(), item.getId(), orderCount);
//Then
fail("재고 수량 부족 예외");
}
@Test
public void 주문취소() {
//Given
Member member = createMember();
Item item = createBook("시골 JPA", 10000, 10);
int orderCount = 2;
Long orderId = orderService.order(member.getId(), item.getId(), orderCount);
//When
orderService.cancelOrder(orderId);
//Then
Order getOrder = orderRepository.findOne(orderId);
assertEquals("주문 취소시 상태는 CANCEL 이다.",OrderStatus.CANCEL, getOrder.getStatus());
assertEquals("주문이 취소된 상품은 그만큼 재고가 증가해야 한다.", 10, item.getStockQuantity());
}
}
=
= orderSearch를 완성시키는 과정
📍OrderSearch.java
@Getter @Setter
public class OrderSearch {
private String memberName;
private OrderStatus orderStatus; // 주문 상태[ORDER, CANCEL]
}
public List<Order> findAll(OrderSearch orderSearch){ }
동적쿼리 : 특정 조건들이나 상황에 따라 변경되는 쿼리를 의미
JPQL ?
JPA에서 지원하는 다양한 방식의 쿼리 중 하나
- 객체 그 자체를 테이블이라 생각하는 대표적인 객체지향 쿼리
- 현재 DB에 대한 지식이 없다는 가정 하에 사용할 때 유리
Entity 객체 그 자체가 Table이며, 어떤 Table이 존재하는 지 일일히 분석할 필요없이 객체들만 보고 쿼리를 짤 수 있는 특징- JPQL 쿼리를 처리하는 것이 EntityManager를 활용하는 것