| 글의 목적
제가 처음 Jpa를 공부하기 시작하고 JpaRepository 내부에 구현되어 있는 여러 메소드를 구경했을 때 신기해서 구현되어 있는 메소드를 사용해보곤 했습니다. 그 중 대표적으로 사용한 메소드가 deleteById()와 같은 삭제 메소드였죠. 단순히 메소드를 사용하던 저는 팀 프로젝트에서 Soft-Delete 와 Hard-Delete의 개념에 대해서 알게 되었습니다. 이해하는 것도, 사용하는 것도 그리 어렵지 않았지만 이러한 개념을 이제서야 알게 되어 아쉽기도 했습니다. 이번 기회에 이 부분에 대해 정리를 하자는 생각이 들어 글을 작성합니다!
만약 저처럼 JpaRepository의 deleteBy~() 메소드를 사용하시면서 Soft-Delete에 대해 모르셨다면, 그러한 분들에게는 새로운 개념을, 이미 Soft - Delete를 사용을 하고 계셨다면 다시 한번 복습을 하면서 어떻게 사용을 하면 더 편할 수 있는지 생각할 수 있는 계기가 되면 좋을 것 같습니다!
| Soft Delete vs Hard Delete
Soft Delete (Logical Delete)
- DB에서 삭제를 할 때 실제 Row가 삭제 되지 않으며 flag를 통한 제어 방식
- 컬럼의 자료형은 boolean 혹은 datetime을 사용합니다.
UPDATE '테이블명' SET is_deleted = 1 WHERE id = 'id번호'
Hard Delete (Physical Delete)
- SQL의 명령어를 통해 DB에서 실제로 데이터가 삭제되는 방식
DELETE FROM '테이블명' WHERE id = 'id번호'
그렇다면, 어떤 방식을 사용하는 것이 좋을까?
-> 무조건적으로 이것이 옳다. 저것은 틀리다라는 것은 없습니다. 저 또한 이 부분에 대해서 찾아봤고 많은 글들이 Soft Delete를 권장하고 더 많이 사용하고 있었지만 오히려 Hard Delete를 권장하는 글도 읽어봤습니다. 이 부분에 대해서 아래 사이트에서 각 부분에 따라 어느 것이 더 이점이 있는지 정리가 되어있습니다. 그러므로 장단점에 대해 좀 더 자세히 알고 싶으면 아래 사이트를 꼭 보시면 좋을 것 같습니다!
[Soft Delte]
- Advantages are that you keep the history (good for auditing) and you don't have to worry about cascading a delete through various other tables in the database that reference the row you are deleting.
[Hard Delete]
- Unique index ensures data integrity by preventing multiple occurrences of a row at the database level.Having soft delete prevents usage of Unique index.
| 그렇다면, Soft - Delete는 어떻게 사용하면 좋을까?
@Where
- JPA에서 Soft - Delete를 활용하기 위해 @Where 를 사용할 수 있습니다. 아래 docs의 설명에 적혀있는 것처럼 soft - deletes에 흔히 사용되곤 합니다.
@Entity
@Table(name = "table_product")
@Where(clause = "deleted=false")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
private boolean deleted = Boolean.FALSE;
}
- 위의 예제코드처럼 @Where 어노테이션을 통해 Product 엔티티의 default 조건을 지정할 수 있습니다.
즉, deleted가 false인 값만 가져오는 것입니다. - 하지만, @Where는 무조건 적용이 되기 때문에 삭제되지 않은 데이터를 가져오고 싶을 경우에는 다른 방식을 적용해야 합니다.
- 그럴 경우, @FilterDef을 사용해야 한다고 하네요!! 아래는 @FilterDef와 관련된 예제입니다.
@SQLDelete
We are using the @SQLDelete annotation to override the delete command. Every time we execute the delete command, we actually have turned it into a SQL update command that changes the deleted field value to true instead of deleting the data permanently.
@Entity
@Table(name = "table_product")
@SQLDelete(sql = "UPDATE table_product SET deleted = true WHERE id=?")
@Where(clause = "deleted=false")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
private boolean deleted = Boolean.FALSE;
}
- 위와 같은 경우 Product의 Repository인 productRepository.deleteByid(1L); 을 했을 때, 쿼리문은 아래와 같이 실행됩니다.
DELETE FROM product WHERE id = 'id번호';
- 이처럼, 기존의 delete문을 update문으로 오버라이딩을 할 수 있습니다.
(참고)
'Develop' 카테고리의 다른 글
주요 Java / MySQL / Spring 버전 정리 (0) | 2022.02.08 |
---|---|
@Transactional이란? @Transactional의 옵션은?? (0) | 2021.11.15 |
Deadlock - 교착상태 (0) | 2021.08.24 |