[22/03/07] 장바구니 기능 구현(1)

Que Lin·2022년 3월 7일
0

처음 해보는 장바구니 기능 구현!
괜히 쫄았지만 좋아요랑 비슷한 기능이라 생각하니 쉽게 할 수 있었다.
wishList도 이것과 비슷하게 구현하면 될 것 같다.

🧑 장바구니 저장하기

1. Entity

CartEntity 설계는 3테이블 조인을 했다.
현재 장바구니와 회원, 장바구니에 담을 강의

package com.phl.cocolo.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Getter
@Setter
@Table(name = "cart_table")
public class CartEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cart_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    private MemberEntity memberEntity;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "onClass_id")
    private OnClassEntity onClassEntity;


    public static CartEntity toCartSaveEntity(MemberEntity memberEntity,
                                              OnClassEntity onClassEntity){
        CartEntity cartEntity = new CartEntity();

        cartEntity.setMemberEntity(memberEntity);
        cartEntity.setOnClassEntity(onClassEntity);

        return cartEntity;

    }
}

2. CartDatailDTO

테이블 조인을 하고 DetailDTO를 가져올 때,
주석으로 페이지에 보여줄 것을 먼저 정하면 계획적으로 가져올 수 있는 것 같다.
내가 장바구니에서 보여줄 것 : 강의 소개> 제목/ 사진/ 가격

package com.phl.cocolo.dto;

import com.phl.cocolo.entity.CartEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CartDetailDTO {
    private Long cartId;
    private Long memberId;
    private Long onClassId;

    // 장바구니에서 보여줄 것 : 온클래스 제목/ 온클래스 사진/ 가격 / 장바구니 리스트의 가격
    private String onClassTitle;
    private int onClassPrice;
    private String onClassFileName;



    public static CartDetailDTO toCartDetailDTO(CartEntity cartEntity){
        CartDetailDTO cartDetailDTO = new CartDetailDTO();

        cartDetailDTO.setCartId(cartEntity.getId());

        cartDetailDTO.setMemberId(cartEntity.getMemberEntity().getId());
        cartDetailDTO.setOnClassId(cartEntity.getOnClassEntity().getId());

        cartDetailDTO.setOnClassTitle(cartEntity.getOnClassEntity().getOnClassTitle());
        cartDetailDTO.setOnClassPrice(cartEntity.getOnClassEntity().getOnClassPrice());
        cartDetailDTO.setOnClassFileName(cartEntity.getOnClassEntity().getOnClassFileName());
        return cartDetailDTO;
    }
}

3. findAll.html(강의 전체조회 화면) 중 일부

장바구니 버튼을 누르면 ajax로 onClassId,memberId를 /cart/save로 post로 보낸다.

<button type="button" class="btn bg-gradient-primary btn-sm me-2"
                                    th:onclick="saveCart([[${onClass.onClassId}]],[[${session.loginId}]])">장바구니에 담기
                            </button>

<script>
    function saveCart(onClassId,memberId) {
        console.log(onClassId + memberId);
        $.ajax({
            type: 'post',
            url: '/cart/save',
            data: {
                'onClassId': onClassId,
                'memberId': memberId
            },
            dataType: 'json',
            success: function (data) {
                if (data) {
                    alert('장바구니에 저장되었습니다.')
                    location.reload();
                } else {
                    alert('이미 장바구니에 있습니다.')
                }
            },
            error: function () {
                alert('ajax 실패');
            }
        });
    };
</script>

4.CartController

Controller에서 회원의 장바구니에 이미 강의가 들어있는지 체크한 후에 boolean값으로 view에 보내준다.
없으면 true => alert('장바구니에 저장되었습니다.')
있으면 false => alert('이미 장바구니에 있습니다.')

    private final CartService cs;
    private final MemberService ms;


    @PostMapping("/save")
    public @ResponseBody boolean
    save(@ModelAttribute CartSaveDTO cartSaveDTO) {
//        장바구니에 onClassId 와 memberId가 없으면 저장되고 true 를 반환, 
// 이미 저장했다면 false 를 반환
       if(cs.checkCart(cartSaveDTO)) {
           cs.save(cartSaveDTO);
           return true;
       } else {
           return false;
       }
    }

5.CartService

회원 장바구니 체크와 저장을 한다

@Service
@RequiredArgsConstructor
public class CartServiceImpl implements CartService{
    private final CartRepository cr;
    private final MemberRepository mr;
    private final OnClassRepository or;

    @Override
    public boolean checkCart(CartSaveDTO cartSaveDTO) {
         Optional<CartEntity> checkCart = cr.findByMemberEntity_IdAndOnClassEntity_Id(cartSaveDTO.getMemberId(), cartSaveDTO.getOnClassId());
         if(checkCart.isEmpty()){
             return true;
         }
         return false;
    }

    @Override
    public Long save(CartSaveDTO cartSaveDTO) {
        MemberEntity memberEntity = mr.findById(cartSaveDTO.getMemberId()).get();
        OnClassEntity onClassEntity = or.findById(cartSaveDTO.getOnClassId()).get();
        return cr.save(CartEntity.toCartSaveEntity(memberEntity,onClassEntity)).getId();
    }
}

6.CartRepository

memberEntity에서 memberId를 onClassEntity onClassId를 가지고 가서 있는지 확인한다.
처음 이렇게 repository로 조인한 테이블에서 값을 찾아오는데, 의외로 직관적이게 되어있어서 어렵지 않았다.

public interface CartRepository extends JpaRepository<CartEntity,Long> {
    Optional<CartEntity> findByMemberEntity_IdAndOnClassEntity_Id(Long memberId, Long onClassId);

    List<CartEntity> findByMemberEntity_Id(Long memberId);

    void deleteAllByMemberEntity_Id(Long memberId);
}

장바구니 체크도 잘 되고, 저장도 잘 된다.
나는 장바구니에서 강의 구매를 할 예정이다.
벤치마킹한 인프런에서도 그렇게 되어있기 때문에^^*

profile
1일 1커밋 1일 1벨로그!

0개의 댓글