실질적으로 데이터를 삭제하는 것이 아니라, 논리적으로만 삭제하고 db에 데이터를 남기는 방식이다. 가령, 회원 정보의 경우 status라는 칼럼으로 현재 활동 중인 계정인지, 탈퇴 처리된 계정인지 나눠 status가 active인 경우만 조회를 하는 식이다.
논리 삭제의 가장 큰 이점은 복구가 가능하다는 것이다. 사실 상 비활성 상태로 관리하는것이기 때문에, 상태값을 바꿈으로서 쉽게 복구할 수 있다.
우선 삭제를 하지 않기 때문에 저장공간을 많이 필요로 한다.
또, 회원 데이터를 조회할 때마다 status가 active인지 확인을 해줘야한다.
회원 데이터는 광범위하게 쓰이는데 매번 status가 active인지 확인하는 코드를 쓰기엔 번거롭다.
Member member = memberRepository.findById(id)
.orElseThrow();
if (member.getStatus() == DELETED) {
throw new ...
}
따라서 JPA에서 제공하는 @Where 애노테이션을 사용하여 적용한다.
@Where(clause = "status = 'ACTIVE'")
원래 이 @Where라는 어노테이션을 쓴대서 적용했더니 다음과 같은 경고가 나왔다.
'org.hibernate.annotations.Where' is deprecated since version 6.3'
따라서 위 문서에 따라 @SQLRestriction으로 수정하였다.
@SQLRestriction("status is ACTIVATE")
이를 엔터티 위에 붙여주면 해당 엔터티가 조회될 때 이 조건이 추가된다.
유의할 점은, 이 기능은 Hibernate가 엔티티를 로딩할 때만 자동 적용되기 때문에 JPQL / @Query에는 자동으로 안 붙는다.
내가 개발 중인 서비스의 경우, 탈퇴한지 7일간 해당 계정으로 가입 못 한다는 조건이 있어, 관련 함수는 JPA 함수가 아닌 @Query로 작성하였다.
@Query(
value = """
select *
from member
where email = :email
and status = 'DELETED'
""",
nativeQuery = true
)
Optional<Member> findByDeletedStatus(String email);
@Modifying
@Query(
value = """
UPDATE member
SET email = NULL
WHERE id = :id
""",
nativeQuery = true
)
void deletePrevEmail(@Param("id") Long id);
soft delete를 위해
https://dev-leonie.tistory.com/43
https://sesam-dev.tistory.com/196
https://velog.io/@youmakemesmile/Spring-Data-JPA-JPQL-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95Query-nativeQuery-DTO-Mapping-function#nativequery