처음 해보는 장바구니 기능 구현!
괜히 쫄았지만 좋아요랑 비슷한 기능이라 생각하니 쉽게 할 수 있었다.
wishList도 이것과 비슷하게 구현하면 될 것 같다.
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;
}
}
테이블 조인을 하고 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;
}
}
장바구니 버튼을 누르면 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>
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;
}
}
회원 장바구니 체크와 저장을 한다
@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();
}
}
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);
}
장바구니 체크도 잘 되고, 저장도 잘 된다.
나는 장바구니에서 강의 구매를 할 예정이다.
벤치마킹한 인프런에서도 그렇게 되어있기 때문에^^*