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;
    }
}

1 3만 delete
nice

 

 

 

참고

https://tech.yangs.kr/23