[스프링 부트 쇼핑몰 프로젝트 with JPA] 15. 장바구니 조회

2023. 10. 16. 20:02·Web & Android/스프링 부트 쇼핑몰 프로젝트 with JPA
이 내용은 스프링 부트 쇼핑몰 프로젝트 with JPA 책을 학습한 내용입니다.

1. CartDetailDto

  • 장바구니 조회 페이지에 전달할 Dto 클래스
  • CartItem 객체와 비슷함. 따라서 List 에 담겨서 전달됨
@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;
    }
}

2. CartItemRepository

  • 장바구니 페이지에 전달할 CartDetailDto 리스트를 쿼리 하나로 조회하는 JPQL 문
  • 지연 로딩이기 때문에 최적화를 위해서 아래 코드와 같이 DTO의 생성자를 이용하여 조회 결과를 DTO 객체로 변환 후 반환할 수 있음
@Query("select new kr.spring.cart.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(@Param("cartId") Long cartId);

3. CartService

  • 현재 로그인한 유저의 장바구니안에 존재하는 상품(들) 조회 로직
  • 로그인 유저 정보 -> 유저의 cart 조회 -> cart 를 참조하는 CartItem 조회 (cartDetailDto 로 변환)
// 현재 로그인한 회원의 정보를 이용하여 장바구니에 들어있는 상품을 조회
    @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;
    }

4. CartController

  • 장바구니 페이지로 이동하는 로직
@GetMapping("/cart")
    public String orderHist(Principal principal, Model model) {
        List<CartDetailDto> cartDetailList = cartService.getCartList(principal.getName());

        model.addAttribute("cartItems", cartDetailList);

        return "cart/cartList";
    }

장바구니 조회 페이지

1. 장바구니 조회 페이지 View

2. 총 주문 금액

  • 주문할 상품을 체크하거나 해제할 경우 총 주문 금액을 구하는 함수 및 호출
<!-- cartList.html -->
$(document).ready(function(){
      $("input[name=cartChkBox]").change( function(){
        getOrderTotalPrice();
      });
    });

    function getOrderTotalPrice(){
      var orderTotalPrice = 0;
      $("input[name=cartChkBox]:checked").each(function() {
        var cartItemId = $(this).val();
        var price = $("#price_" + cartItemId).attr("data-price");
        var count = $("#count_" + cartItemId).val();
        orderTotalPrice += price*count;
      });

      $("#orderTotalPrice").html(orderTotalPrice+'원');
    }

3. 상품 전체 선택 및 해제

  • checkall 태그의 프로퍼티 값이 checked 라면 cartChkBox 태그를 모두 checked 상태로 변경
  • checked 가 아니라면 모두 checked 상태를 해제
  • 마지막에 총 주문 금액을 수정하는 getOrderTotalPrice() 함수 호출
function checkAll(){
      if($("#checkall").prop("checked")){
        $("input[name=cartChkBox]").prop("checked",true);
      }else{
        $("input[name=cartChkBox]").prop("checked",false);
      }
      getOrderTotalPrice();
    }

4. 장바구니 상품 수량 변경

  • 수량 부분의 수량을 변경하면 changeCount() 함수 호출
  • 변경된 수량을 적용하기 위해 총 주문 금액을 수정하는 getOrderTotalPrice() 함수 호출
<input type="number" name="count" th:id="'count_' + ${cartItem.cartItemId}"
                                       th:value="${cartItem.count}" min="1"
                                       onchange="changeCount(this)" class="form-control mr-2" >
function changeCount(obj){
      var count = obj.value;
      var cartItemId = obj.id.split('_')[1];
      var price = $("#price_" + cartItemId).data("price");
      var totalPrice = count*price;
      $("#totalPrice_" + cartItemId).html(totalPrice+"원");
      getOrderTotalPrice();
      updateCartItemCount(cartItemId, count);
    }
  • data-key-value 형태의 자료구조
<!-- id = price{CartItemId} 엘리먼트에 data 자료구조 생성 후 key = price 에 대한 value 지정 -->
<span th:id="'price_' + ${cartItem.cartItemId}"
      th:data-price="${cartItem.price}"
      th:text="${cartItem.price} + '원'" class="align-self-center mr-2">
</span>
  • 장바구니에 들어있는 상품의 수량을 변경하면 CartItem 의 count 값도 수정되야 하므로 마지막에 updateCartItemCount() 함수 호출
function updateCartItemCount(cartItemId, count){
      var token = $("meta[name='_csrf']").attr("content");
      var header = $("meta[name='_csrf_header']").attr("content");

			// 상품 Id 값은 PathVariable, 수량(count)은 QueryString 
      var url = "/cartItem/" + cartItemId+"?count=" + count;

      $.ajax({
        url      : url,
        type     : "PATCH",
        beforeSend : function(xhr){
          /* 데이터를 전송하기 전에 헤더에 csrf값을 설정 */
          xhr.setRequestHeader(header, token);
        },
        dataType : "json",
        cache   : false,
        success  : function(result, status){
          console.log("cartItem count update success");
        },
        error : function(jqXHR, status, error){

          if(jqXHR.status == '401'){
            alert('로그인 후 이용해주세요');
            location.href='/members/login';
          } else{
            alert(jqXHR.responseJSON.message);
          }

        }
      });
    }

5. CartItem Entity

  • 수량 변경을 위한 메소드 추가
// 장바구니에 담겨있는 수량을 변경하는 메소드
    public void updateCount(int count) {
        this.count = count;
    }

6. CartService

  • updateCount() 메소드를 호출하는 로직을 추가
  • 현재 로그인한 유저와 해당 장바구니 상품의 저장한 유저가 같은지 검증
// 현재 로그인한 회원과 해당 장바구니 상품을 저장한 회원이 같은지 검사
    @Transactional(readOnly = true)
    public boolean validateCartItem(Long cartItemId, String email) {
        Member curMember = memberRepository.findByEmail(email);
        CartItem cartItem = cartItemRepository.findById(cartItemId).orElseThrow(EntityNotFoundException::new);

        Member savedMmeber = cartItem.getCart().getMember();

        if(!StringUtils.equals(curMember.getEmail(), savedMmeber.getEmail())) {
            return false;
        }

        return true;
    }

7. CartController

  • 위에 존재하는 updateCartItemCount() 함수 호출 시 전송되는 PATCH 요청에 대한 Controller
  • cartService.updateCartItemCount() 메소드 호출
  • 상품의 개수를 0으로 지정할 시 에러 메시지 반환
// 장바구니 상품의 수량을 업데이트하는 요청 처리
    @PatchMapping("/cartItem/{cartItemId}")
    public @ResponseBody ResponseEntity updateCartItem(@PathVariable("cartItemId") Long cartItemId, int count, Principal principal) {

        if(count <= 0) {
            return  new ResponseEntity<String>("최소 1개 이상 담아주세요.", HttpStatus.BAD_REQUEST);
        } else if(!cartService.validateCartItem(cartItemId, principal.getName())) {
            return new ResponseEntity<String>("수정 권한이 없습니다.", HttpStatus.FORBIDDEN);
        }

        cartService.updateCartItemCount(cartItemId, count);
        return new ResponseEntity<Long>(cartItemId, HttpStatus.OK);
    }
저작자표시 비영리 변경금지 (새창열림)

'Web & Android > 스프링 부트 쇼핑몰 프로젝트 with JPA' 카테고리의 다른 글

[스프링 부트 쇼핑몰 프로젝트 with JPA] 17-1. 게시판 - Entity  (1) 2023.10.16
[스프링 부트 쇼핑몰 프로젝트 with JPA] 16.장바구니 상품 삭제 & 주문  (0) 2023.10.16
[스프링 부트 쇼핑몰 프로젝트 with JPA] 14. 장바구니 담기  (1) 2023.10.16
[스프링 부트 쇼핑몰 프로젝트 with JPA] 13. 주문 취소  (0) 2023.10.16
[스프링 부트 쇼핑몰 프로젝트 with JPA] 12. 구매 내역 조회  (0) 2023.10.16
'Web & Android/스프링 부트 쇼핑몰 프로젝트 with JPA' 카테고리의 다른 글
  • [스프링 부트 쇼핑몰 프로젝트 with JPA] 17-1. 게시판 - Entity
  • [스프링 부트 쇼핑몰 프로젝트 with JPA] 16.장바구니 상품 삭제 & 주문
  • [스프링 부트 쇼핑몰 프로젝트 with JPA] 14. 장바구니 담기
  • [스프링 부트 쇼핑몰 프로젝트 with JPA] 13. 주문 취소
woojin._.
woojin._.
여러가지 개발을 해보며 발생하는 이야기들에 대한 블로그입니다:)
  • woojin._.
    Jin's Dev Story
    woojin._.
  • 전체
    오늘
    어제
    • 분류 전체보기 (829)
      • Tools (25)
        • eGovFrame (3)
        • GeoServer (3)
        • QGIS (2)
        • LabelImg (2)
        • Git (6)
        • GitHub (1)
        • Eclipse (7)
        • Visual Studio (1)
      • Web & Android (121)
        • SpringBoot (37)
        • Three.js (2)
        • Spring Data JPA (9)
        • 스프링 부트 쇼핑몰 프로젝트 with JPA (25)
        • Thymeleaf (4)
        • Spring Security (15)
        • Flutter (29)
      • Programming Language (61)
        • JAVA (27)
        • JavaScript (14)
        • Dart (2)
        • Python (15)
        • PHP (3)
      • Database (43)
        • PostgreSQL (32)
        • MYSQL (7)
        • Oracle (3)
        • MSSQL (1)
      • SERVER (17)
        • TCP_IP (3)
        • 리눅스 (7)
        • AWS (7)
      • Coding Test (445)
        • 백준[JAVA] (108)
        • 프로그래머스[JAVA] (260)
        • 알고리즘 고득점 Kit[JAVA] (3)
        • SQL 고득점 Kit[ORACLE] (74)
      • CS 지식 (49)
        • [자료구조] (14)
        • [네트워크] (12)
        • [데이터베이스] (10)
        • [알고리즘] (9)
        • [운영체제] (4)
      • 기타 (6)
      • 자격증 & 공부 (62)
        • 정보처리기사 (2)
        • SQLD (6)
        • 네트워크관리사 2급 (5)
        • 리눅스마스터 1급 (44)
        • 리눅스마스터 2급 (1)
        • ISTQB (3)
        • 시스템보안 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 인기 글

  • 태그

    programmers
    postgresql
    Flutter
    baekjoon
    백준
    DB
    Oracle
    자바
    데이터
    리눅스마스터 1급
    python
    리눅스
    Spring Security
    springboot
    플러터
    리눅스마스터
    spring
    backjoon
    CS
    스프링 부트 쇼핑몰 프로젝트 with JPA
    시큐리티
    CS지식
    데이터베이스
    pcce 기출문제
    스프링
    Linux
    스프링부트
    프로그래머스
    Java
    JPA
  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
woojin._.
[스프링 부트 쇼핑몰 프로젝트 with JPA] 15. 장바구니 조회
상단으로

티스토리툴바