Spring/Spring Boot
[Spring] 스프링 엔티티 삭제 시점 히스토리 기록하기 (Soft Delete)
민돌v
2022. 4. 20. 18:12
생성시간과, 삭제시간은 jpaAuditing으로 기록이 가능했는데, 삭제시점을 자동을 체크해주고 싶어서 찾아보니 jpaAuditing에는 없었다 흨,,ㅠ
그러다
하이버네이트에서, delete 시점을 체크할 수 있는 @SqlDelete 와 default 조건절을 붙히는 @where 를 발견했다..!
Soft Delete
ex) `UPDATE table SET delete = 1 WHERE id = 2` 형태로 ROW가 삭제 되지 않고 flag를 통한 제어 하는 방식
delete가 되더라도, 데이터를 지우는게 아닌, column 값을 변경하여, 데이터를 제어하는 방법이다,
@SQLDelete Annotation
@SQLDelete 어노테이션을 통해, 실제 삭제가 이루어질때 수행 할 쿼리를 적으면 된다.
- ex) @SQLDelete("UPDATE product SET del=1 WHERE id = ?")
- 그럼 productRepository.deleteById(1L) 형태로 진행이 되면 'DELETE FROM product WHERE id = 1' 형태로 쿼리가 동작 하는 것이 아닌
- 'Update product SET del 1 WHERE id = 1' 형태로 쿼리가 발생되어 동작하게 된다.
@Where Annotation
- @Where 어노테이션은 Entity의 Default 조건을 지정 할 수 있는 어노테이션 이다.
- 장점은 'Soft Delete'로 인하여, 객체 그래프에서 발생 할 수 있는 문제를 신경쓰지 않아도 된다.
- 또한,@OneToMany, @ManyToOne 등의 조인이 걸린 경우에도 따로 쿼리 조건을 지정 할 수 있기 때문에 편해진다.
단점은, 무조건 조건이 적용 되기 때문에, 삭제된 걸 가져와야 하는 상황에는 또 애매해진다.
(이 경우는 @FilterDef을 활용하면 된다고 한다는데,, 음)
soft delete 적용해보기
@MappedSuperclass // 맴버변수가 컬럼이 되도록
@EntityListeners(AuditingEntityListener.class) // 변경되었을 때 자동으로 기록합니다.
public class Timestamped {
@CreatedDate // 최초 생성 시점
private LocalDateTime createdAt;
@LastModifiedDate // 마지막 변경 시점
private LocalDateTime modifiedAt;
//삭제 시점
private LocalDateTime deletedAt;
}
@Getter
@Entity
@ToString
@NoArgsConstructor
@Where(clause = "deleted_at IS NULL")
@SQLDelete(sql = "UPDATE post SET deleted_at = CURRENT_TIMESTAMP where id = ?")
public class Post extends Timestamped {
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
@Column
private Long id;
//제목
@Column
String title;
//내용
@Column
String contents;
@Builder
public Post(String title, String contents) {
this.title = title;
this.contents = contents;
}
}
참고