JPA

[JPA] @SQLRestriction으로 soft delete 구현하기

kkang._.h00n 2025. 12. 21. 21:00

개요

데이터 삭제 정책이 soft delete라면, 데이터 조회 시 delete 상태 여부를 확인하는 조건을 일일이 넣어주어야 할 것이다.

@SQLRestriction 어노테이션을 통해 SQL의 where절에 delete 상태 여부를 체크하는 조건을 넣는 방법을 소개하려 한다.

 

 

문제

코드를 살펴보자. 먼제 Hospital 엔티티이다.

@Entity
@Table(name = "hospitals")
class Hospital(

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long? = null,

    val name: String,
    
    ...

    //삭제가 된 상태라면, 해당 필드에 값 존재
    var deletedAt: LocalDateTime? = null

) : BaseTime()

엔티티에서는 삭제 시간을 기록하는 deletedAt이 있다. 해당 필드의 값이 존재한다면 그 시간에 삭제가 된 것이고, 존재하지 않는다면 아직 삭제된 상태가 아니다.

 

해당 프로젝트에서는 데이터가 삭제 처리되었을 경우 보여주지 않아야 한다. 그렇다면 모든 Hospital 목록을 보여주어야 하면 정책에 따라 아래처럼 쿼리를 작성해야 할 것이다.

interface HospitalRepository : JpaRepository<Hospital, Long> {
    @Query("""
        select h
        from hospital h
        where h.deletedAt is null
    """)
    fun findAllWithOutDeleted(@Param("id") id: Long)
}

 

이렇게 되면 기능이 추가될 때마다 findById()나 메서드쿼리 같은 Spring Data Jpa에서 제공하는 기능을 사용하지 못하고 쿼리를 재작성 해야 할 것이다.

 

 

적용

//어노테이션 적용
@SQLRestriction("deleted_at IS NULL")
@Entity
@Table(name = "hospitals")
class Hospital(

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long? = null,

    val name: String,
    
    ...

    var deletedAt: LocalDateTime? = null

) : BaseTime()

엔티티 조회 시 SQL의 공통된 조건을 적용해야 한다면, @SQLRestriction의 조건을 넣어주면 간단하게 해결된다.

 

 

결과

findAll() 메서드를 통한 조회 시, 설정한 조건이 where절에 적용된 것을 볼 수 있다!