Spring

Spring delete 메소드 주의사항

AlgoPoolJa 2023. 2. 14. 22:33

Delete 쿼리 종류

TL;DR

  • 속도 측면에서는 deleteAllInBatch() 가 가장 빠르다.
  • test 코드를 제외하고는 deleteAllInBatch() 를 사용하지 말자

설명

delete(entity)

해당 메서드는 CrudRepository 에 등록되어 있는 메서드 입니다. 엔티티를 파라미터로 받아 해당 엔티티를 삭제합니다.

deleteAll()

해당 메서드는 CrudRepository 에 등록되어 있는 메서드로 해당 레포지토리에서 관리 되는 모든 entity 를 삭제합니다.

deleteAllInBatch()

해당 메서드는 JpaRepository 에 등록되어 있는 메서드로 모든 entity 를 한번의 함수 실행으로 삭제합니다.

예시

코드의 예시로 설명해보겠습니다.

예시로 다룰 엔티티는 Member 로 다음과 같습니다.

@Where(clause = "deleted_at is null")
@SQLDelete(sql = "update member set deleted_at = now() where id = ?")
@Entity
class Member(
    @Column(name = "name")
    val name: String,
) {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private val id: Long? = null
​
    @Column(name = "deleted_at")
    private val deletedAt: String? = null
}
@SpringBootTest
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
class MemberRepositoryTest(
    val memberRepository: MemberRepository,
) {
    @Test
    @DisplayName("멤버 삭제")
    fun deleteMember() {
        println("---------------------MemberSave START---------------------")
        val member = memberRepository.save(MemberFactory.of("test"))
        val member2 = memberRepository.save(MemberFactory.of("test"))
        val member3 = memberRepository.save(MemberFactory.of("test"))
        println("---------------------MemberSave END---------------------")
​
        println("---------------------Member DELETE START---------------------")
        memberRepository.delete(member)
        println("---------------------Member DELETE END---------------------")
​
        println("---------------------Member DELETE ALL START---------------------")
        memberRepository.deleteAll()
        println("---------------------Member DELETE ALL END---------------------")
​
        println("---------------------Member DELETE ALL IN BATCH START---------------------")
        memberRepository.deleteAllInBatch()
        println("---------------------Member DELETE ALL IN BATCH END---------------------")
    }
}
---------------------MemberSave START---------------------
Hibernate: 
    insert 
    into
        member
        (deleted_at, name) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        member
        (deleted_at, name) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        member
        (deleted_at, name) 
    values
        (?, ?)
---------------------MemberSave END---------------------
​
​
​
---------------------Member DELETE START---------------------
Hibernate: 
    select
        member0_.id as id1_0_0_,
        member0_.deleted_at as deleted_2_0_0_,
        member0_.name as name3_0_0_ 
    from
        member member0_ 
    where
        member0_.id=? 
        and (
            member0_.deleted_at is null
        )
Hibernate: 
    update
        member 
    set
        deleted_at = now() 
    where
        id = ?
---------------------Member DELETE END---------------------
​
​
​
---------------------Member DELETE ALL START---------------------
Hibernate: 
    select
        member0_.id as id1_0_,
        member0_.deleted_at as deleted_2_0_,
        member0_.name as name3_0_ 
    from
        member member0_ 
    where
        (
            member0_.deleted_at is null
        )
Hibernate: 
    update
        member 
    set
        deleted_at = now() 
    where
        id = ?
Hibernate: 
    update
        member 
    set
        deleted_at = now() 
    where
        id = ?
---------------------Member DELETE ALL END---------------------
​
​
​
---------------------Member DELETE ALL IN BATCH START---------------------
Hibernate: 
    delete 
    from
        member
---------------------Member DELETE ALL IN BATCH END---------------------
​

코드의 결과를 살펴보면 delete(entity) 와 deleteAll() 는 soft delete 가 잘 작동하는 것을 확인할 수 있습니다. 또한 deleteAll() 은 하나의 레코드마다 하나의 update 쿼리가 생성되는것을 확인할 수 있습니다. 하지만 deleteAllInBatch() 는 모든 레코드는 hard delete 하는것을 확인할 수 있습니다.

따라서 속도를 위해 deleteAllInBatch() 를 사용할 수 있지만 비즈니스 로직에서 쓰는것은 hard delete 할 일이 아닌 이상 매우 경계하면서 사용해야 합니다.