@SQLDelete(sql = "UPDATE AST_ATTR_ELEMENTS SET IS_DELETED = 1 WHERE AST_ATTR_ELEMENT_ID = ?")
@SQLRestriction("IS_DELETED = 0")
개요
이번 프로젝트에서는 모든 조회 및 검색에서 is_deleted가 false인, 즉 논리적으로 삭제되지 않은 데이터만을 처리하도록 요구하고 있습니다.
이를 해결할 수 있는 방법은 다양합니다. 예를 들어, 단순히 Repository에 조건을 추가하는 방법, @Query 어노테이션을 활용하는 방법 등이 있습니다. 하지만 이번 기회에 새롭게 알게 된 @SQLRestriction 어노테이션에 대해 공부한 내용을 정리하고자 합니다.
@SQLRestriction 어노테이션이란❓
Hibernate에서 @SQLRestriction은 특정 엔티티 필드에 대해 SQL 조건을 설정하는데 사용됩니다.
이를 통해 데이터베이스 쿼리를 생성할 때 추가적인 제약 조건을 적용할 수 있으며, 기본적으로 해당 필드에 대한 조회나 수정이 이루어질 때마다 이 제약 조건이 자동으로 반영됩니다.
특히 필터링이 필요하거나, 논리적으로 삭제된 데이터를 제외하고 싶은 경우 등에 유용하게 사용됩니다.
주요 사용 사례
- 논리 삭제 처리: is_deleted 같은 필드가 있을 때, 물리적으로 데이터를 삭제하지 않고, 논리적으로만 삭제 처리한 데이터를 제외하는 조건을 설정할 수 있습니다.
- 특정 값 필터링: 예를 들어, 특정 상태 값만을 가진 데이터를 조회해야 할 때 사용할 수 있습니다.
사용 방법
SQLRestriction("is_deleted = false")
public class User {
...
}
위와 같이 어노테이션을 사용하면 되고, Entity에 해당 어노테이션이 선언되어 있으면, search 쿼리에 자동으로 where 절이 추가됩니다.
@SQLRestriction 사용 X
Hibernate: select h1_0.hub_id,h1_0.address,h1_0.created_at,h1_0.created_by,h1_0.deleted_at,h1_0.deleted_by,h1_0.is_deleted,h1_0.latitude,h1_0.longitude,h1_0.name,h1_0.updated_at,h1_0.updated_by from p_hubs h1_0 where h1_0.hub_id=?
@SQLRestriction 사용 O
Hibernate: select h1_0.hub_id,h1_0.address,h1_0.created_at,h1_0.created_by,h1_0.deleted_at,h1_0.deleted_by,h1_0.is_deleted,h1_0.latitude,h1_0.longitude,h1_0.name,h1_0.updated_at,h1_0.updated_by from p_hubs h1_0 where h1_0.hub_id=? and (h1_0.is_deleted = false)
앞서 말했다 싶이 select 쿼리의 where절에 추가되기 때문에 로그가 길어서 보기가 쉽지 않지만 중요한 부분은 마지막 부분입니다.
@SQLRestriction어노테이션을 사용하면 where절에 추가한 is_deleted = false 쿼리가 추가된 것을 확인할 수 있습니다.
@SQLRestriction 어노테이션의 장단점
장점
- 간단한 전역 필터링
- 모든 조회에 대해 일관된 제약 조건을 적용할 수 있습니다.
- 코드 가독성 증가
- 쿼리 작성 시 중복된 조건을
반복적으로 추가할 필요가 없습니다.
- 쿼리 작성 시 중복된 조건을
- 논리 삭제 처리
- 데이터베이스에서 물리적으로 삭제되지 않은 데이터를 제외하는 데 적합합니다.
단점
- 제약 조건이 고정적
- @SQLRestriction에 지정된 조건은
동적으로 변경할 수 없으므로, 조건이 고정된 상황에서만 사용이 가능합니다.
- @SQLRestriction에 지정된 조건은
- 복잡한 필터링 어려움
- 복잡한 조건이 필요한 경우에는 @SQLRestriction보다는 직접적인 쿼리 작성이나 @Filter 같은 다른 방식을 사용하는 것이 더 나을 수 있습니다.
@SQLDelete
- 정의: Hibernate 엔티티의 삭제 동작을 커스터마이징하는 어노테이션.
- 기본적으로, Hibernate는 EntityManager.remove() 또는 session.delete()를 호출하면 물리적 삭제를 수행하는 SQL (DELETE FROM)을 실행합니다.
- @SQLDelete를 사용하면, 물리적 삭제 대신 특정 SQL 쿼리를 실행하도록 변경할 수 있습니다.
여기서는 논리적 삭제를 구현하기 위해 UPDATE 문을 실행하도록 설정했습니다.
코드설명:
@SQLDelete(sql = "UPDATE AST_ATTR_ELEMENTS SET IS_DELETED = 1 WHERE AST_ATTR_ELEMENT_ID = ?")
이 코드는 Hibernate에게 엔티티가 삭제될 때, 실제로 DELETE 문 대신 다음 SQL을 실행하라고 지시합니다.
UPDATE AST_ATTR_ELEMENTS SET IS_DELETED = 1 WHERE AST_ATTR_ELEMENT_ID = ?
결과적으로, 해당 레코드의 IS_DELETED 필드가 1로 설정되며, 논리적으로 삭제된 상태로 표시됩니다.
@SQLRestriction
- 정의: 엔티티를 조회할 때 특정 조건을 추가해 필터링하는 Hibernate 어노테이션.
- 논리적 삭제된 데이터(IS_DELETED = 1)는 보통 사용자에게 표시되지 않아야 합니다.
- @SQLRestriction은 Hibernate가 데이터를 가져올 때 특정 조건을 추가하여 삭제된 데이터를 자동으로 제외하도록 만듭니다.
모든 조회 쿼리에 IS_DELETED = 0 조건을 자동으로 추가합니다.
예를 들어:
session.createQuery("FROM AST_ATTR_ELEMENTS")
위와 같은 쿼리를 실행할 때 Hibernate는 내부적으로 아래와 같은 SQL을 실행합니다:
SELECT * FROM AST_ATTR_ELEMENTS WHERE IS_DELETED = 0
💡논리적으로 삭제?
논리적으로 데이터를 삭제한다는 것은 데이터 자체를 물리적으로 삭제하지 않고,
사용자가 접근할 수 없도록 처리하거나 비활성화 시키는 방식을 말합니다. 데이터베이스나 시스템에서는 데이터를 실제로 지우지 않고도 삭제된 것처럼 보이게 할 수 있습니다.
'공부 > Spring Boot' 카테고리의 다른 글
[Java] Spring Boot - JPA @PrePersist, @PreUpdate (0) | 2024.11.20 |
---|---|
Spring Boot Webflux란 (0) | 2024.01.12 |
[Spring Boot] ResponseEntity (0) | 2023.08.16 |