항해 99(9기)/항해 일일

항해 99 35일차

jossiya 2022. 10. 24. 20:47
1. member와의 연관관계 끊기
2. SOFT_DELETE 적용해보기
3. 멤버 권한줘서 컨트롤러별 접근막기

2.JPA + Hibernate 개발 환경에서의 구현

Hibernate를 사용하는 애플리케이션에서 Soft Delete를 구현하는 방법과 발생할 수 있는 문제들을 해결할 수 있는 방법들에 대해서 알아보겠습니다.

개발 환경

  • Spring Boot 2.5.10
  • Postgresql 14.1
  • Java 11(Open Jdk Azul)

구현

@Entity
@Where(clause = "deleted = false")
@SQLDelete(sql = "UPDATE posts SET deleted = true WHERE id = ?")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Posts {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String title;

    @Column(nullable = false)
    private String content;

    @Column(nullable = false)
    private boolean deleted;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "post", cascade = CascadeType.REMOVE)
    private List<Comments> comments = new ArrayList<>();

    public Posts(String title, String content) {
        this.title = title;
        this.content = content;
    }

    public void delete() {
        this.deleted = true;
    }

    public void addComment(Comments comment) {
        this.comments.add(comment);
    }

}
@Entity
@Where(clause = "deleted = false")
@SQLDelete(sql = "UPDATE comments SET deleted = true WHERE id = ?")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Comments {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String content;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private Posts post;

    @Column(nullable = false)
    private boolean deleted;

    public Comments(String content, Posts post) {
        this.content = content;
        this.post = post;
        this.post.addComment(this);
    }

    public void delete() {
        this.deleted = true;
    }
    
}

예제 소스 코드에서 사용할 게시글과 댓글 엔티티 클래스입니다. soft delete를 구현하기 위해 boolean 타입의 필드로 삭제 유무를 구분하고 메소드를 통해 객체의 상태를 변경하여 삭제합니다.

@Where(clause = "deleted = false")

엔티티 조회 쿼리의 where절에 반드시 포함되는 조건을 설정할 수 있습니다. 개발자의 실수로 쉽게 누락할 수 있기 때문에 애노테이션을 사용해서 글로벌하게 설정하는 것이 좋습니다. 또한 Lazy Loading으로 발생하는 조회 쿼리의 where절에 조건을 포함시키기 위해서는 반드시 사용해야합니다. 하지만 JPQL 또는 HQL이 아닌 native SQL을 사용할 때는 적용되지 않기 때문에 주의해야합니다.

@SQLDelete(sql = "UPDATE comments SET deleted = true WHERE id = ?")