이 내용은 스프링 부트 쇼핑몰 프로젝트 with JPA 책을 학습한 내용입니다.
1. CartItemDto
- 제품 상세 페이지에서 장바구니에 담을 상품 Id 와 수량을 전달 받을 DTO 객체 생성
@Getter
@Setter
public class CartItemDto {
@NotNull(message = "상품 아이디는 필수 입력 값입니다.")
private Long itemId; // 상품 아이디
@Min(value = 1, message = "최소 1개 이상 담아주세요.")
private int count; // 상품 수량
}
2. Cart Entity
- 회원 한 명당 1개의 장바구니를 갖으므로 처음 장바구니에 상품을 담을 때는 해당 회원의 장바구니를 생성해야함
- 멤버를 파라미터로 받아서 장바구니를 생성하는 static 메소드 추가
// 회원의 장바구니 생성
public static Cart createCart(Member member) {
Cart cart = new Cart();
cart.setMember(member);
return cart;
}
3. CartItem Entity
- 장바구니에 담을 CartItem 객체를 생성하는 메소드 추가
- 장바구니에 담겨 있는 상품을 또 장바구니로 담았을 경우 수량을 증가시키는 메소드 추가
// 장바구니에 담을 상품 엔티티를 생성하는 메소드
public static CartItem createCartItem(Cart cart, Item item, int count) {
CartItem cartItem = new CartItem();
cartItem.setCart(cart);
cartItem.setItem(item);
cartItem.setCount(count);
return cartItem;
}
// 장바구니에 담을 수량을 증가시켜 주는 메소드
public void addCount(int count) {
this.count += count;
}
4. CartRepository
- 현재 로그인한 유저의 장바구니(Cart)를 찾기 위해서 쿼리 메소드 추가
public interface CartRepository extends JpaRepository<Cart, Long> {
// 현재 로그인한 회원의 Cart 엔티티를 찾기 위한 메소드
Cart findByMemberId(Long memberId);
}
5. CartItemRepository
- 상품이 장바구니에 들어있는지 조회하는 쿼리 메소드 추가
public interface CartItemRepository extends JpaRepository<CartItem, Long> {
CartItem findByCartIdAndItemId(Long cartId, Long itemId);
}
6. CartService 생성
- 유저의 장바구니가 존재하지 않다면 생성
- 장바구니 안에 해당 상품이 존재한다면 수량을 증가시키고, 그렇지 않다면 추가
@Service
@RequiredArgsConstructor
@Transactional
public class CartService {
private final ItemRepository itemRepository;
private final MemberRepository memberRepository;
private final CartRepository cartRepository;
private final CartItemRepository cartItemRepository;
private final OrderService orderService;
public Long addCart(CartItemDto cartItemDto, String email) {
Item item = itemRepository.findById(cartItemDto.getItemId()).orElseThrow(EntityNotFoundException::new);
Member member = memberRepository.findByEmail(email);
Cart cart = cartRepository.findByMemberId(member.getId());
if(cart == null) {
cart = Cart.createCart(member);
cartRepository.save(cart);
}
CartItem savedCartItem = cartItemRepository.findByCartIdAndItemId(cart.getId(), item.getId());
if(savedCartItem != null) {
savedCartItem.addCount(cartItemDto.getCount());
return savedCartItem.getId();
} else {
CartItem cartItem = CartItem.createCartItem(cart, item, cartItemDto.getCount());
cartItemRepository.save(cartItem);
return cartItem.getId();
}
}
7. CartController 생성
- 제품 상세 페이지에서 넘어온 CartItemDto 객체와 email 을 파라미터로 CartService.addCart() 메소드를 수행
@Controller
@RequiredArgsConstructor
public class CartController {
private final CartService cartService;
@PostMapping("/cart")
public @ResponseBody ResponseEntity order(@RequestBody @Valid CartItemDto cartItemDto, BindingResult bindingResult, Principal principal) {
if(bindingResult.hasErrors()) {
StringBuilder sb = new StringBuilder();
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for(FieldError fieldError : fieldErrors) {
sb.append(fieldError.getDefaultMessage());
}
return new ResponseEntity<String> (sb.toString(), HttpStatus.BAD_REQUEST);
}
String email = principal.getName();
Long cartItemId;
try {
cartItemId = cartService.addCart(cartItemDto, email);
} catch (Exception e) {
return new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<Long>(cartItemId, HttpStatus.OK);
}
8. 제품 상세 페이지 장바구니 담기
- "장바구니 담기" 버튼을 누르면 수행되는 Ajax 코드
function addCart(){
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
var url = "/cart";
var paramData = {
itemId : $("#itemId").val(),
count : $("#count").val()
};
var param = JSON.stringify(paramData);
$.ajax({
url : url,
type : "POST",
contentType : "application/json",
data : param,
beforeSend : function(xhr){
/* 데이터를 전송하기 전에 헤더에 csrf값을 설정 */
xhr.setRequestHeader(header, token);
},
dataType : "json",
cache : false,
success : function(result, status){
alert("상품을 장바구니에 담았습니다.");
location.href='/';
},
error : function(jqXHR, status, error){
if(jqXHR.status == '401'){
alert('로그인 후 이용해주세요');
location.href='/members/login';
} else{
alert(jqXHR.responseText);
}
}
});
}
- "장바구니 담기" 버튼을 누르면 Ajax 코드 수행되게 설정
<button type="button" class="btn btn-light border border-primary btn-lg" onclick="addCart()">장바구니 담기</button>