1. 책 주문 하기 코드
public ResponseEntity<BaseResponse> bookdemand(Long bookId, Integer quantity, HttpServletRequest request) {
final String lockname = bookId + "lock";
final RLock lock = redissonClient.getLock(lockname);
HttpSession session = request.getSession(false);
if (session == null) {
return BaseResponse.toResponseEntity(ErrorCode.Forbidden);
} else {
try{
if (!lock.tryLock(1,3, TimeUnit.SECONDS)){
System.out.println("키 점거 실패");
orderLogger.info("키 점거 실패");
return BaseResponse.toResponseEntity(ErrorCode.CONFLICT_KEY);
}
Member member = (Member)request.getSession()
.getAttribute(SessionConst.LOGIN_MEMBER);
Book book = entityManager.find(Book.class, bookId);
bookorder(book,quantity,member);
orderLogger.info("bookId:{}, memberId:{}, state:{}, quantity:{}, totalPrice:{}",bookId,member.getId(),"order",quantity,book.getPrice()*quantity);
}catch (Exception e){
e.printStackTrace();
}finally {
if (lock != null && lock.isLocked()){
lock.unlock();
}
}
return BaseResponse.toResponseEntity(SuccessCode.ORDER_SUCCESS);
}
}
@Transactional
public void bookorder(Book book, Integer quantity, Member member){
Long inven = book.getInventory()-quantity;
if (inven<0){ // 재고가 0보다 작으면 잘 못된 주문
throw new CustomException(ErrorCode.INVALIDATION_NOT_ENOUGH);
}else if(inven ==0 ){ // 재고가 0이면 품절 -> modifiedAt 변경
jumoonRepository.save(new Jumoon(member, book, quantity));
book.inventoryChangeBook(inven);
bookRepository.save(book);
}else { // 품절되지 않으면 inventory만 바꿔줌
jumoonRepository.save(new Jumoon(member, book, quantity));
book.batchBook(inven);
bookRepository.save(book);
}
}
- 주문을 완료하고 book.batchbook / book.inventoryChangeBook으로 재고량을 바꿔주었다.
- 하지만 다시 save를 해주어야 변경사항이 적용되었으며 그 전에는 적용되지 않았다.
2. 주문 취소 코드
public ResponseEntity<BaseResponse> cancelbook(Long jumoonId, HttpServletRequest request) {
Member member = (Member)request.getSession()
.getAttribute(SessionConst.LOGIN_MEMBER);
Jumoon jumoon = jumoonRepository.findByIdAndMember(jumoonId, member).orElseThrow(
()-> new CustomException(ErrorCode.Forbidden)
);
Long bookid = jumoon.getBook().getId();
final String lockname = bookid + "lock";
final RLock lock = redissonClient.getLock(lockname);
try{
if (!lock.tryLock(1,3, TimeUnit.SECONDS)){
System.out.println("키 점거 실패");
orderLogger.info("키 점거 실패");
return BaseResponse.toResponseEntity(ErrorCode.CONFLICT_KEY);
}
Book book = entityManager.find(Book.class, bookid);
Long inven = book.getInventory()+jumoon.getQuantity();
book.inventoryChangeBook(inven);
bookcancle(book,inven,jumoon);
orderLogger.info("bookId:{}, memberId:{}, state:{}, quantity:{}, totalPrice:{}",book.getId(),member.getId(),"cancel",jumoon.getQuantity(),book.getPrice()*jumoon.getQuantity());
}catch (Exception e){
e.printStackTrace();
}finally {
if (lock != null && lock.isLocked()){
lock.unlock();
}
}
return BaseResponse.toResponseEntity(SuccessCode.ORDER_SUCCESS);
}
@Transactional
public void bookcancle(Book book, Long inven, Jumoon jumoon){
book.inventoryChangeBook(inven);
jumoonRepository.delete(jumoon);
}
- 앞서 주문과 다르게 취소를 했을 때 book.inventoryChangeBook으로 재고량을 변경 시킨 뒤에 BookRepository를 이용해 save를 해주지 않아도 재고량이 다시 원상 복구 되었다.
3. 다른 해결 방법
@Transactional
public void bookorder(Book book, Integer quantity, Member member){
Long inven = book.getInventory()-quantity;
if (inven<0){ // 재고가 0보다 작으면 잘 못된 주문
throw new CustomException(ErrorCode.INVALIDATION_NOT_ENOUGH);
}else if(inven ==0 ){ // 재고가 0이면 품절 -> modifiedAt 변경
book.inventoryChangeBook(inven);
jumoonRepository.save(new Jumoon(member, book, quantity));
// book.inventoryChangeBook(inven);
// bookRepository.save(book);
}else { // 품절되지 않으면 inventory만 바꿔줌
book.batchBook(inven);
jumoonRepository.save(new Jumoon(member, book, quantity));
// book.batchBook(inven);
// bookRepository.save(book);
}
}
- 주문 저장이전에 재고량을 변경 시켜주면 해결이 된다.
- save메서드를 사용하면 해당엔티티와 연관된 다른 엔티티들도 함께 영속성 컨텐스트에 등록