장바구니에 들어있는 상품 조회 기능 구현
요즘 들어 코딩테스트 준비로 바쁘게 살아가고 있다. 프로그래머스에서 Spring 인턴 공고가 떠서 그걸 준비하고 있는데 역시 코테는 하면 할수록 내가 많이 부족하다는 것을 느낀다. 알고리즘과 자료구조에 대해 더욱 빡세게 공부해야겠다. 여튼 코테준비를 하면서 프로젝트에 신경을 많이 못 썼는데 이제 프로젝트도 조금씩 만들어나가야겠다.
가장 마지막에 장바구니까지 구현했다. 이제는 장바구니에 들어있는 상품을 조회하는 기능을 구현해보기로 했다.
언제나 그랬듯 장바구니 조회 페이지에 전달할 DTO 클래스를 먼저 만들어야한다. 이를 위해 CartDetail
이라는 네이밍으로 DTO를 구현하기로 했다.
CartDetailDto.java
package com.shop.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class CartDetailDto {
private Long cartItemId; // 장바구니 상품 아이디
private String itemNm; // 상품명
private int price; // 상품 금액
private int count; // 수량
private String imgUrl; // 상품 이미지 경로
public CartDetailDto(Long cartItemId, String itemNm, int price, int count, String imgUrl) {
this.cartItemId = cartItemId;
this.itemNm = itemNm;
this.price = price;
this.count = count;
this.imgUrl = imgUrl;
}
}
이제는 장바구니 페이지에 전달할 CartDetailDto 리스트를 쿼리 하나로 조회하는 JPQL 문을 작성한다.
CartItemRepository.java
package com.shop.repository;
// (...import 생략)
import com.shop.dto.CartDetailDto;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface CartItemRepository extends JpaRepository<CartItem, Long> {
CartItem findByCartIdAndItemId(Long cartId, Long itemId);
@Query("select new com.shop.dto.CartDetailDto(ci.id, i.itemNm, i.price, ci.count, im.imgUrl) " +
"from CartItem ci, ItemImg im " +
"join ci.item i " +
"where ci.cart.id = :cartId " +
"and im.item.id = ci.item.id " +
"and im.repimgYn = 'Y' " + // 상품의 대표 이미지 가져오기
"order by ci.regTime desc"
)
List<CartDetailDto> findCartDetailDtoList(Long cartId);
}
연관 관계 매핑을 지연 로딩으로 설정할 경우, 엔티티에 매핑된 다른 엔티티를 조회할 때 추가적으로 쿼리문이 실행되게 된다. 따라서 성능 최적화가 필요한 경우, 위와 같이 DTO의 생성자를 이용하여 반환 값으로 DTO 객체를 생성할 수 있다.
"new com.shop.dto.CartDetailDto(ci.id, i.itemNm, i.price, ci.count, im.imgUrl)"
처럼 new 키워드와 해당 DTO의 패키지, 클래스명을 적어준다. 또한, 생성자의 파라미터 순서는 DTO 클래스에 명시한 순서로 넣어주어야한다.CartService.java
package com.shop.service;
// (import 생략)
import com.shop.dto.CartDetailDto;
import java.util.ArrayList;
import java.util.List;
@Service
@RequiredArgsConstructor
@Transactional
public class CartService {
// ...코드 생략
@Transactional(readOnly = true)
public List<CartDetailDto> getCartList(String email){
List<CartDetailDto> cartDetailDtoList = new ArrayList<>();
Member member = memberRepository.findByEmail(email);
Cart cart = cartRepository.findByMemberId(member.getId()); // 현재 로그인한 회원 장바구니 엔티티 조회
if(cart == null){ // 장바구니에 상품을 담지 않았을 경우 빈 리스트 반환
return cartDetailDtoList;
}
cartDetailDtoList = cartItemRepository.findCartDetailDtoList(cart.getId());
// 장바구니에 담겨있는 상품 정보를 조회
return cartDetailDtoList;
}
}
장바구니 페이지로 이동할 수 있도록 기존 Controller 클래스에 메소드를 추가해야한다.
CartControlle.java
package com.shop.controller;
// .. 기존 임포트 생략
import com.shop.dto.CartDetailDto;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
@RequiredArgsConstructor
public class CartController {
// .. 코드 생략
@GetMapping(value = "/cart")
public String orderHist(Principal principal, Model model) {
List<CartDetailDto> cartDetailList = cartService.getCartList(principal.getName());
model.addAttribute("cartItems", cartDetailList);
return "cart/cartList";
}
}
List<CartDetailDto> cartDetailList = cartService.getCartList(principal.getName());
현재 로그인한 사용자의 이메일 정보를 이용하여 장바구니에 담겨있는 상품 정보를 조회한다.model.addAttribute("cartItems", cartDetailList);
로 조회한 장바구니 상품 정보를 뷰로 전달한다.