-
Notifications
You must be signed in to change notification settings - Fork 4
[JPA study 5주차 이해림]
제일 중요 비즈니스 로직들이 얽혀서 어떻게 작동되는 지 알 수 있어서
public static Order creatOrder(Member member, Delivery delivery, OrderItem... orederItems){
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;
// 오더가 연관관계를 걸면서 세팅이 됨.(상태와 주문시간까지) 정리 유용.
이러한 스타일이 중요한 이유 생성하는 지점을 변경할 때 'creatOrder'이것만 바꾸면 됨.
this.setStatus(OrderStatus.CANCEL);
for(OrderItem orderItem: orderItems) {
orderItem.cancel();
}
// 만약 고객이 오더를 두번하면 오더아이템이 두 개 생성 그렇기에 취소할 땐 각각 캔슬을 날려줘야 함.
public void cancel() {
getItem().addStock(count);
}
// 캔슬하면 일단 재고가 없다는 경우가 있으므로 재고를 채워줘야 함.
public int getTotalPrice() {
int totalPrice = 0;
for (OrderItem orderItem : orderItems) {
totalPrice += orderItem.getTotalPrice();
}
return totalPrice;
}
// 토탈프라이스를 0으로 초기화 후 오더아이템으로 루프를 돌면서 오더아이템에 있느느 토탈프라이스를 가져옴 왜냐 주문할 떄 가격과 수량이 있으므로
상품 주문할 때 상품의id만 넘어오게
orderRepository.save(order); 왜 이 한줄로만 세이브할까? 이유는 Order.java에 있는 caseade떄문 오더를 퍼시스트하면 모든 오더를 강제로 퍼시스트 딜리버리도 마찬가지 그래서 하나만 저장해줘도 오더와 딜리버리 둘 다 세이브가 된 거임!
참고로 OrderItem orderitem1 = new OrderItem(); 이런 식으로 개발하는 사람이 있음 그러나, 생성로직에서 필드를 넣거나 수정할 떄 매우 유지보수가 어려워짐. 분산되기에 그렇기에 이 외의 다른 스타일의 생성을 막아야 함.(protected 또는 @NoArgsConstructor(access = AccessLevel.PROTECTED))
@Transactional
public void cancelOrder(Long orderId) {
Order order = orderRepository.findOne(orderId)
order.cancel();
}
// 주문취소로직, 조회할 때에는 id만 가져옴. 로직이 매우 간단한데 비지니스 로직을 만들어서 배송완료된 것만 빼고 재고를 0으로 바꾸어 캔슬을 만들어 놓음. 여기서 JPA의 강점이 나옴. 지금 데이터를 변경한 것인데 밖에서 업데이트 쿼리를 직접만들어야 함 원래는 근데 jpa는 데이터만 바꾸면 알아서 바뀐 변경 포인트를 데이터베이스에 쿼리가 알아서 날아감 이런 경우는 오더의 데이터를 바꾼 것이기에 jpa 자체에서 오더 디비에 쿼리를 날려줄 것임.
비즈니스 로직은 대부분 엔티티에 있음 이런 스타일은 도메인 모델 패턴이라 칭함, 서비스 계층은 단순히 엔티티에 필요한 요청을 위임하는 역할 엔티티는 비지니스 로직이 거의 없고 서비스 계층에서 대부분의 비즈니스 로직을 처리하는 것을 트렌잭션 스크립트 패턴이라 함.
상품주문_재고수량초과의 int orderCount가 11인 경우 왜 실패하나? 오더서비스에서 오더로 가고 다음 오더아이템을 만들 때 리무브소톡 비즈니스 로직이 실행 리무브스톡에 대해 단위 테스트가 있는 것이 별도로 존재하는 것이 중요 (강의에서는 안함, 그러나 실무에선 그렇게 하면 좋다)
JPA에서 동적 쿼리를 어떻게 해결해야 하는가?
public List<Order> findAll(OrderSearch orderSearch) {
em.createQuery("select o from order o join o.member m", Order.class)
}
//오더 서치 조인 (객체이기 떄문에 참고하는 스타일로 조인)
만약, orderSearch의 조건이 다 있다면
return em.createQuery("select o from order o join o.member m"+
"where o.status = : status"+
"and m.name like :name", Order.class)
.setParameter("status", orderSearch.getOrderStatus())
.setParameter("name", orderSearch.getMemberName())
.setMaxResults(1000) //최대 1000건
.getResultList();
// "where o.status = : status"+"and m.name like :name" 만약 이 구문이 없으면 동적 쿼리임.
동적 쿼리를 JPQL로 처리 번거롭고, 실수가 많음
동적 퀴리를 JPA Criteria로 처리 치명적인 단점이 있음 스펙을 만들 때 어떻게 하면 깔끔하게 될게 고민하는 것이 일반적인데 이 코드를 보면 유지보수성이 아예 없음
그러면 어떻게 해결할 수 있을까? query dsl 라는 라이브러리가 있음.
Welcome to the 2024-1-JPA-Study wiki!