4-frame-photos-map / backend

네컷지도(전국 네컷사진관 정보 제공, 리뷰 공유 사이트) 백엔드 API 개발
6 stars 3 forks source link

fix : 찜 삭제 ObjectOptimisticLockingFailureException #76

Closed zuminzi closed 1 year ago

zuminzi commented 1 year ago

목적

2개의 API 요청이 같은 row 삭제 시도하여 생긴 충돌 문제(트랜잭션 낙관적 동시성 실패) 해결

문제 상황

  • 프론트 측에서 개발 중인 토스트 메세지 기능과 충돌하여 동시성 문제 발생
  • 프론트에서 토스트 메세지 기능 수정 후, 앞으로 개발 완료될 UI에서는 이와 같은 문제 일어날 확률이 적다고 합니다. 그래도 일단 예외처리는 해두었는데 불필요 시 예외처리 코드는 삭제예정입니다.
    
    delete 
    from
    favorite 
    where
    id=?
    2023-04-07 01:16:56.385 TRACE 1 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [86]
    2023-04-07 01:16:56.386 TRACE 1 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_] : [BIGINT]) - [86]
    Hibernate: 
    update
    shop 
    set
    create_date=?,
    modify_date=?,
    favorite_cnt=?,
    place_name=?,
    review_cnt=?,
    road_address_name=?,
    star_rating_avg=? 
    where
    id=?
    2023-04-07 01:16:56.386 TRACE 1 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [TIMESTAMP] - [2023-03-16T10:56:09]
    2023-04-07 01:16:56.386 TRACE 1 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [TIMESTAMP] - [2023-04-07T01:16:56.386509453]
    2023-04-07 01:16:56.386 TRACE 1 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [INTEGER] - [1]
    2023-04-07 01:16:56.386 TRACE 1 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [VARCHAR] - [인생네컷]
    2023-04-07 01:16:56.386 TRACE 1 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [INTEGER] - [0]
    2023-04-07 01:16:56.386 TRACE 1 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [6] as [VARCHAR] - [서울 용산구 이태원로 171]
    2023-04-07 01:16:56.386 TRACE 1 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [7] as [DOUBLE] - [0.0]
    2023-04-07 01:16:56.386 TRACE 1 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [8] as [BIGINT] - [4157]
    Hibernate: 
    delete 
    from
    favorite 
    where
    id=?
    2023-04-07 01:16:56.388 TRACE 1 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [86]
    2023-04-07 01:16:56.390  INFO 1 --- [nio-8080-exec-6] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements
    2023-04-07 01:16:56.395 ERROR 1 --- [nio-8080-exec-6] c.i.f.g.error.GlobalExceptionHandler     : Exception

org.springframework.orm.ObjectOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; statement executed: delete from favorite where id=?; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; statement executed: delete from favorite where id=?


## 작업 상세 내용
- [x] 찜 추가 및 삭제 트랜잭션 커밋 단위 축소
   - 찜 수 갱신 코드 ShopService로 분리
   - Shop 엔티티에 `@DynamicUpdate` 적용하여 수정된 컬럼만 업데이트 반영
-  [x] 찜 삭제 `ObjectOptimisticLockingFailureException` 예외 처리
   - exists로 검사 후 테이블에 존재하면 찜 삭제 재시도, 재실패하거나 존재하지 않을 시 오류 처리

## 참고 사항
- [ObjectOptimisticLockingFailureException 발생 시 예외처리](https://www.inflearn.com/questions/266817/objectoptimisticlockingfailureexception)