사용자 탈퇴 시 IS_DELETED = true로 변경되도록하는 SOFT-DELETED를 하고 있다.
@SQLRestriction("IS_DELETED = 0")
문제)
사용자 탈퇴 시, SOFT-DELETED가 되어 IS_DELETED = true가 된다.
사용자와 게시판 데이터는 1:N관계가 맺어 있다.
사용자가 탈퇴했더라도, 게시판 데이터는 조회하고 싶은 상황이다.
참고링크)
[TIL, 일일 회고] 2024.09.11 - Hibernate @SQLRestriction 어노테이션: 사용법과 장단점 분석
개요이번 프로젝트에서는 모든 조회 및 검색에서 is_deleted가 false인, 즉 논리적으로 삭제되지 않은 데이터만을 처리하도록 요구하고 있습니다. 이를 해결할 수 있는 방법은 다양합니다. 예를 들
pixx.tistory.com
@SQLRestriction()의 단점 중 제약 조건이 고정적이라는 점이 있다.
백오피스에서 삭제된 데이터도 조회해야 한다면 문제가 발생할 수 있습니다.
또한, @SQLRestriction 어노테이션이 엔티티 클래스 내부에서 고정된 조건을 설정하는 데 사용되기 때문에, 도메인 외부에서는 이 필터링 조건을 동적으로 변경하거나 제어할 수 없다는 한계가 있습니다.
💡@SQLRestriction()의 단점
- 제약 조건이 고정적
@SQLRestriction에 지정된 조건은 동적으로 변경할 수 없으므로, 조건이 고정된 상황에서만 사용이 가능합니다.
- 복잡한 필터링 어려움
복잡한 조건이 필요한 경우에는 @SQLRestriction보다는 직접적인 쿼리 작성이나 @Filter 같은 다른 방식을 사용하는 것이 더 나을 수 있습니다.
🔍 왜 조회되지 않는가?
현재 User 엔티티에 @SQLRestriction("IS_DELETED = 0")가 적용되어 있기 때문에 Hibernate가 내부적으로 생성하는 모든 쿼리에 IS_DELETED = 0 조건이 자동 추가됩니다.
이로 인해, 게시글을 조회할 때 발생하는 SQL을 보면 아래와 같은 형태가 됩니다:
SELECT a.* FROM ASSETS a
LEFT JOIN USERS u ON a.CREATOR_ID = u.USER_ID
WHERE u.IS_DELETED = 0;
즉, Asset이 User와 조인하는 과정에서, User가 삭제(IS_DELETED = 1)된 경우 해당 조인 결과가 필터링되어 전체 Asset 레코드가 조회되지 않는 상황이 발생합니다.
해결 방법 1)
사용자 entity와 게시판 entity에 걸려있는 @RQLRestriction을 주석처리 해두었더니, 사용자가 IS_DELETED=true가 되었어도, 게시글이 조회가 된다.
@SQLRestriction("IS_DELETED = 0")
당연히 된다.. 이건 없애는거니까..
하지만, 그럼 논리적 삭제가 사라지는거니.. 이 방법은 패스
해결 방법2)
직접적인 쿼리 작성이나 @Filter 같은 다른 방식을 사용하는 것이 더 나을 수 있습니다.
이걸 사용하라는 글을 봤는데,, 우선 더 적용해봐야겠다...
@FilterDef(name = "deletedFilter", parameters = @ParamDef(name = "deleted", type = "boolean"))
@Filter(name = "deletedFilter", condition = "IS_DELETED = :deleted") // 필터 정의
해결 방법3)
1️⃣ @SQLRestriction 제거 후, @Where 사용
현재 @SQLRestriction("IS_DELETED = 0")가 User 엔티티에 적용되어 있어 모든 쿼리에 강제 적용됩니다.
이를 제거하고, 일반적인 User 조회에서는 @Where(clause = "IS_DELETED = 0")를 사용하여 필터링하면 문제를 해결할 수 있습니다.
✅ User 엔티티 변경
import org.hibernate.annotations.Where;
@Entity
@Where(clause = "IS_DELETED = 0") // 일반적인 User 조회에서만 적용
@Table(name = "USERS")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(name = "USER_ID", nullable = false)
private String userID;
@Column(name = "IS_DELETED", nullable = false)
private Boolean isDeleted;
}
👉 @SQLRestriction을 제거하고, @Where를 적용하면 일반적으로 User를 조회할 때만 IS_DELETED = 0이 적용됩니다.
해결 방법4)
findAllByID jpa를 사용하지 말고 쿼리로 작성?
'공부 > Spring Boot' 카테고리의 다른 글
| JPA의 영속 상태(Persistent State) (0) | 2025.05.05 |
|---|---|
| JPA Specification (0) | 2025.03.28 |
| @SQLRestriction 어노테이션: 사용법과 장단점 분석 (1) | 2024.11.20 |
| [Java] Spring Boot - JPA @PrePersist, @PreUpdate (0) | 2024.11.20 |
| Spring Boot Webflux란 (0) | 2024.01.12 |