Soft Delete
•
데이터베이스에서 직접 데이터를 삭제하는 Hard Delete 방식의 반대
•
보통 Boolean 필드(컬럼)을 추가해서 해당 컬럼을 통해 삭제 여부를 판단한다.
SpringBoot에서의 구현
import org.hibernate.annotations.*;
@Entity
@Getter
@NoArgsConstructor
@Table(name = "account")
@SQLDelete(sql = "UPDATE account SET is_deleted = true WHERE id = ?")
@FilterDef(name = "deletedAccountFilter")
@Filter(name = "deletedAccountFilter", condition = "is_deleted = false")
public class AccountEntity extends BaseEntity {
...
@ColumnDefault("0")
@Column(name = "is_deleted", nullable = false)
private Boolean isDeleted;
}
Java
복사
@SQLDelete
@SQLDelete(sql = "UPDATE account SET is_deleted = true WHERE id = ?")
=>
public void remove(Account account) {
accountRepository.delete(
accountRepository.findById(account.getId()).orElseThrow()
);
}
=>
UPDATE
account
SET
is_deleted = true
WHERE
id = ?
Java
복사
JPARepository에서 delete 메소드를 호출할 때, DELETE 쿼리가 아닌 SQLDelete 어노테이션 안의 sql에 정의된 쿼리(is_delete를 true로)를 실행시킨다.
@Filter
@FilterDef(name = "deletedAccountFilter")
@Filter(name = "deletedAccountFilter", condition = "is_deleted = false")
---
Specifies that an entity or collection is affected by a named filter declared using FilterDef,
and allows the default filter condition to be overridden for the annotated entity or collection role.
For example, we might apply a filter named Current to an entity like this:
@Entity
@Filter(name = "Current",
deduceAliasInjectionPoints = false,
condition = "{alias}.year = extract(year from current_date)")
class Course {
@Id @GeneratedValue Long id;
int year;
...
}
Java
복사
엔티티에 조건을 지정하고 조건에 맞추어 쿼리를 실행시키는 역할을 한다. 다만 쿼리를 실행하기 전에 엔티티 매니저에서 Session을 통해 Filter를 활성화해야 한다.
HibernateFilterAspect
@Aspect
@Component
@RequiredArgsConstructor
public class HibernateFilterAspect {
private final EntityManager entityManager;
@Before("execution(* com.berry.next.*.application.*.*(..))")
public void enableHibernateFilter() {
Session session = entityManager.unwrap(Session.class);
session.enableFilter("deletedAccountFilter");
}
}
Java
복사
서비스 레이어에서 구현해야 할 내용은 아니라고 생각해서 AOP를 통해서 구현하였다.
후에 @Before("execution(* com.berry.next.*.application.service.*(..))") 로 수정할 예정.