[Spring boot]repository의 save 메소드가 update 쿼리만을 수행하는 경우

한상욱·2024년 12월 27일
0

에러해결모음

목록 보기
7/10
post-thumbnail

사건의 발단

최근 진행하는 프로젝트에서 enum 클래스만을 저장하는 테이블이 필요해졌고, 컬럼은 오직 enum 클래스 하나만 달랑 존재했습니다. 그렇기에 해당 필드만을 PK로 갖는 테이블을 생성하고 save를 통해서 저장하는 api를 제작하는 중 insert쿼리가 아니라 update 쿼리를 수행하는 현상을 마주하였습니다.

@Table
data class Favorite(
    @Id
    @Column
    val category : IngredientCategory,
) {
    fun toResponse() : FavoriteResponseDto = FavoriteResponseDto(category = category)
}

테이블은 위와 같고, Service 계층의 코드는 아래와 같습니다.

    /**
     * 즐겨찾기 재료 추가하기
     */
    @Transactional
    suspend fun createNewFavorite(favoriteRequestDto: FavoriteRequestDto) : FavoriteResponseDto {
        val category = favoriteRepository.findByCategory(favoriteRequestDto.category)
        if (category != null) {
            throw RuntimeException("이미 추가된 재료입니다!")
        }
        val result = favoriteRepository.save(favoriteRequestDto.toEntity())
        return result.toResponse()
    }

이 코드에서는 update 쿼리만을 수행합니다.

해결 방법

Repository가 제공하는 save 메소드는 id 필드가 존재하면 새로운 레코드가 아니라 기존의 레코드를 수정하는 방식으로 동작하게 됩니다. 즉, 제가 작성한 테이블은 PK 하나밖에 없는 테이블이므로 모든 동작이 update로 인식되는 것입니다.

이를 해결하기 위해서 엔티티를 아래와 같이 수정해주었습니다.

@Table
data class Favorite(
    @Id
    @Column
    val category : IngredientCategory,
) : Persistable<IngredientCategory> {

    override fun isNew(): Boolean {
        return true
    }

    override fun getId(): IngredientCategory = this.category

    fun toResponse() : FavoriteResponseDto = FavoriteResponseDto(category = category)
}

Persistable을 상속받아 isNew를 재정의하여 새로운 객체인지 아닌지 판단하도록 임의로 설정할 수 있습니다.

이제 잘 수행되네요 :)

profile
자기주도적, 지속 성장하는 모바일앱 개발자의 기록

0개의 댓글