연관관계
테이블은 외래키를 객체는 id를 쓴다
onetomany하고 밑에 multiablelist mapped by
객체의 연관관계는 팀 회원, 회원 팀이렇게 단방향 둘
테이블은 양방향
onetomanyt(mapped by = "team"이런식
양방향은 널에 위험함 그래서 안쓰는게 좋음
양방향을 쓸거면 순환구조로 그런데 양방향은 서로를 무한참조함 막으려면 toString(),내가 어재 쓴 Json이런거 쓰기
양방향 관계가 키는 누가 같나? order, item이 양방향이면 order_itrm을 만들어서 키를 준다
오더가 오더아이템에 일대다 오더아이템과 아이템이 다대일
onetoone은 헬스장 회원과 라커룸으로 키는 더 많이 쓰이는 쪽에?
@RestController
@RequestMapping("/carts")
class CartController(private val cartService: CartService) {
@PostMapping
fun addToCart(@AuthenticationPrincipal user: UserPrincipal, @RequestBody cartCreateDto: CartCreateDto): ResponseEntity<CartDto> {
val memberId = user.id
val cart = cartService.addToCart(cartCreateDto.menuId, cartCreateDto.storeId, memberId, cartCreateDto.count)
return ResponseEntity.status(HttpStatus.CREATED).body(CartDto.from(cart))
}
@DeleteMapping("/{cartId}")
fun removeFromCart(@AuthenticationPrincipal user: UserPrincipal, @PathVariable cartId: Long): ResponseEntity<String> {
val memberId = user.id
return try {
cartService.removeFromCart(memberId, cartId)
ResponseEntity.ok("성공적으로 제거하였습니다.")
} catch (e: Exception) {
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("제거에 실패했습니다.")
}
}
@DeleteMapping("/member/{memberId}")
fun clearCart(@AuthenticationPrincipal user: UserPrincipal, @PathVariable memberId: String): ResponseEntity<String> {
val memberId = user.id
return try {
cartService.clearCart(memberId)
ResponseEntity.ok("성공적으로 제거하였습니다.")
} catch (e: Exception) {
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("제거에 실패했습니다.")
}
}
@GetMapping("/{cartId}")
fun getCart(@AuthenticationPrincipal user: UserPrincipal, @PathVariable cartId: Long): ResponseEntity<out Any> {
val memberId = user.id
return try {
val cart = cartService.getCart(memberId, cartId)
if (cart.member.id != memberId) {
ResponseEntity.status(HttpStatus.FORBIDDEN).body("You do not have permission to view this cart.")
} else {
ResponseEntity.ok(CartDto.from(cart))
}
} catch (e: Exception) {
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("조회할 수 없습니다.")
}
}
}
카트컨트롤러에서 저 에러메시지를 보디로 보내는건 사실 좋은 방법이 아니란 소리를 들었다.
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("제거에 실패했습니다.")
이게 아니라
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.message.toString())
이렇게 바꿔야 한다. 왜냐면 저렇게 BODY로 메시지를 줘버리면 어떤 상황에도 실패했으면 저 메시지를 주기 때문에 서버에러든 인증 실패든 전부 저 메시지를 주기 때문에 e.message.toString()이걸 넣어야 적절한 메시지가 자동으로 나온다.
@GetMapping("/{cartId}")
fun getCart(@AuthenticationPrincipal user: UserPrincipal, @PathVariable cartId: Long): ResponseEntity<out Any> {
val memberId = user.id
return try {
val cart = cartService.getCart(memberId, cartId)
if (cart.member.id != memberId) {
ResponseEntity.status(HttpStatus.FORBIDDEN).body("You do not have permission to view this cart.")
} else {
ResponseEntity.ok(CartDto.from(cart))
}
} catch (e: Exception) {
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("조회할 수 없습니다.")
}
}
이녀석을
@GetMapping()
@Operation(summary = "카트 조회", description = "주어진 회원 ID, 카트 ID에 해당하는 카트를 조회합니다.")
fun getCarts(@AuthenticationPrincipal user: UserPrincipal): ResponseEntity<out Any> {
val memberId = user.id
return try{
val carts = cartService.getCarts(memberId)
val cartDto = carts.map { CartDto.from(it) }
ResponseEntity.ok(cartDto)
} catch (e: Exception) {
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.message.toString())
}
}
이렇게 바꿨는데, 카트조회는 실제 앱에서도 한명이 주문한것 전부 조회해주기 때문에 cardid를 입력하는 부분을 없애고 if else도 e.message 덕분에 필요없으니 치워버린다.
그리고 서비스 임플은
@Service
class CartServiceImpl(
private val cartRepository: CartRepository,
private val menuRepository: MenuRepository,
private val storeRepository: StoreRepository,
private val memberRepository: MemberRepository
) : CartService {
override fun addToCart(menuId: Long, storeId: Long, memberId: Long, count: Int): Cart {
val menu = menuRepository.findById(menuId).orElseThrow { Exception("Menu not found") }
val store = storeRepository.findById(storeId).orElseThrow { Exception("Store not found") }
val member = memberRepository.findById(memberId).orElseThrow { Exception("Member not found") }
val cart = Cart(menu = menu, store = store, member = member, count = count)
return cartRepository.save(cart)
}
override fun removeFromCart(memberId: Long, cartId: Long) {
val cart = cartRepository.findById(cartId).orElseThrow { Exception("Cart not found") }
if (cart.member.id != memberId) {
throw IllegalAccessException("Not authorized to remove this cart.")
}
cartRepository.deleteById(cartId)
}
override fun clearCart(memberId: Long) {
val member = memberRepository.findById(memberId).orElseThrow { Exception("Member not found") }
val carts = cartRepository.findAllByMember(member)
cartRepository.deleteAll(carts)
}
override fun getCart(memberId: Long, cartId: Long): Cart {
val cart = cartRepository.findById(cartId).orElseThrow { Exception("Cart not found") }
if (cart.member.id != memberId) {
throw IllegalAccessException("Not authorized to view this cart.")
}
return cart
}
}
이녀석을
@Service
class CartServiceImpl(
private val cartRepository: CartRepository,
private val menuRepository: MenuRepository,
private val storeRepository: StoreRepository,
private val memberRepository: MemberRepository
) : CartService {
override fun addToCart(menuId: Long, storeId: Long, memberId: Long, count: Int): Cart {
val menu = menuRepository.findById(menuId).orElseThrow { Exception("Menu not found") }
val store = storeRepository.findById(storeId).orElseThrow { Exception("Store not found") }
val member = memberRepository.findById(memberId).orElseThrow { Exception("Member not found") }
val cart = Cart(menu = menu, store = store, member = member, count = count)
return cartRepository.save(cart)
}
override fun removeFromCart(memberId: Long, cartId: Long) {
val cart = cartRepository.findById(cartId).orElseThrow { Exception("Cart not found") }
if (cart.member.id != memberId) {
throw IllegalAccessException("Not authorized to remove this cart.")
}
cartRepository.deleteById(cartId)
}
override fun clearCart(memberId: Long) {
val member = memberRepository.findById(memberId).orElseThrow { Exception("Member not found") }
val carts = cartRepository.findAllByMember(member)
cartRepository.deleteAll(carts)
}
override fun getCarts(memberId: Long): List<Cart> {
val member = memberRepository.findById(memberId).orElseThrow { Exception("Member not found") }
val carts = cartRepository.findAllByMember(member)
return carts
}
이렇게 만드는데, 전부조회이기 때문에 getcart를 getcarts로 하고, (memberId: Long, cartId: Long) 부분에서 cartid가 있던 이유는 특정 cart를 조회하기 위해서였는데 그 부분을 없에서 그냥 memberid만을 받아오도록 변형시켰다.
val member = memberRepository.findById(memberId).orElseThrow { Exception("Member not found") }:
이 줄은 memberId에 해당하는 회원을 찾는 코드다. memberRepository.findById(memberId)를 통해 해당 ID를 가진 회원을 조회하고 만약 찾는 회원이 없다면, orElseThrow 메서드에 의해 "Member not found"라는 메시지를 가진 Exception이 발생한다.
val carts = cartRepository.findAllByMember(member):
이 줄은 위에서 찾은 회원이 소유한 모든 카트를 조회하는 코드입니다. cartRepository.findAllByMember(member) 메서드는 member 객체를 인자로 받아, 해당 회원이 소유한 모든 카트를 찾아 리스트 형태로 반환합니다.
따라서, 이 두 줄의 코드를 통해 특정 회원이 소유한 모든 카트를 찾아 carts 리스트에 저장하는 작업을 수행
cart도 list가 됬는데 카트하나가 아니라 목록이라 그런것이다.
그래서
override fun getCart(memberId: Long, cartId: Long): Cart {
val cart = cartRepository.findById(cartId).orElseThrow { Exception("Cart not found") }
if (cart.member.id != memberId) {
throw IllegalAccessException("Not authorized to view this cart.")
}
return cart
}
override fun getCarts(memberId: Long): List<Cart> {
val member = memberRepository.findById(memberId).orElseThrow { Exception("Member not found") }
val carts = cartRepository.findAllByMember(member)
return carts
}
이렇게 변한다.
interface CartService {
fun addToCart(menuId: Long, storeId: Long, memberId: Long, count: Int): Cart
fun getCarts(memberId: Long): List<Cart>
fun removeFromCart(memberId: Long, cartId: Long)
fun clearCart(memberId: Long)
}
이것도 getcarts로 바꾸고 cart를 리스트로 바꿨다.
interface CartRepository : JpaRepository<Cart, Long> {
fun findAllByMember(member: Member): List<Cart>
}
이것또한 마찬가지로 리스트로 바꿔준다.
@GetMapping("/{cartId}")
fun getCart(@AuthenticationPrincipal user: UserPrincipal, @PathVariable cartId: Long): ResponseEntity<out Any> {
val memberId = user.id
return try {
val cart = cartService.getCart(memberId, cartId)
if (cart.member.id != memberId) {
ResponseEntity.status(HttpStatus.FORBIDDEN).body("You do not have permission to view this cart.")
} else {
ResponseEntity.ok(CartDto.from(cart))
}
} catch (e: Exception) {
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("조회할 수 없습니다.")
}
}
@GetMapping()
@Operation(summary = "카트 조회", description = "주어진 회원 ID, 카트 ID에 해당하는 카트를 조회합니다.")
fun getCarts(@AuthenticationPrincipal user: UserPrincipal): ResponseEntity<out Any> {
val memberId = user.id
return try{
val carts = cartService.getCarts(memberId)
val cartDto = carts.map { CartDto.from(it) }
ResponseEntity.ok(cartDto)
} catch (e: Exception) {
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.message.toString())
}
}
그리고 다시 컨트롤러로 돌아가서 여기서도 카트를 s를 붙이고 카트이티오를 map으로 받아야 한다. 이때 map를 쓰지 않으면 서비스임플의 겟카트가 작동을 안한다.