본문 바로가기

Java/jpa

JPA Entity soft delete 활용하기

반응형

데이터베이스에서  데이터를 삭제하는 방법 

 

hard delete (물리 삭제)

실제로 delete query를 날려서 데이터베이스에서 실제로 삭제하는 방법이다.

 

soft delete (논리 삭제)

실제로 데이터베이스에서 데이터를 삭제하는것이 아닌  삭제 여부 컬럼을 추가해서 삭제 되었음을 나타내는 방법 

삭제를 하더라도 데이터를 보관해야하는 경우 논리삭제를 활용한다.(유저 정보및 결제내역 등)

 

 

JPA에서 soft delete 하기 

 

먼저 Soft Delete를 위한 준비를 하겠다. 

 

entity 종류 

  • Member
  • Boad 

Member.java

@Entity
@Table (name = "member")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@SQLDelete(sql =" UPDATE Member SET is_deleted = true where member_id = ?")
@Where(clause = "is_deleted = false")
public class Member extends BaseEntity{

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "member_id")
	private Long id;

	@Column(name = "email", unique = true)
	private String email;
    
    	@Column(name = "is_deleted")
	private final Boolean isDeleted = Boolean.FALSE;

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "member" , cascade = CascadeType.ALL, orphanRemoval = true)
	private List<Board> boardList = new ArrayList<>();

 

 

Board.java

@Entity
@Table (name = "board")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Board extends BaseEntity{

   	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "board_id")
	private Long id;

   	@Column(name = "title")
	private String title;

   	@Column(name = "content")
	private String content;
    
    	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name="member_id")
	private Member member;

 

 

@SQLDelete(sql = "")

해당 어노테이션을 작성해두면 엔티티 삭제가 발생할때 hard delete 대신 sql에 작성한 내용대로 쿼리가 실행되게 된다. 

@SQLDelete(sql =" UPDATE Member SET is_deleted = true where member_id = ?")


위 쿼리는 삭제시 is_deleted = true로 업데이트 쿼리가 발생하게 된다. 

 

@Where

soft delete를 했다고 하더라도 조회시에 삭제처리되지 않은 데이터만 가져와야한다. 모든 entity 조회 요청시에 기본값으로 where 조건이 붙게 된다.

@Where(clause = "is_deleted = false")

 

is_deleted 가 false인 경우만 가져오는 쿼리를 작성했다. 앞으로 모든 member 조회시에 기본적으로 where = is_deleted=false가 들어가게 된다. 

 

 

유의사항

1. cascade삭제

soft delete를 실행해서 Member가 삭제되는것을 막았더라도  자식 엔티티가 삭제되지 않은것은 아니다. 

@OneToMany(fetch = FetchType.LAZY, mappedBy = "member" , cascade = CascadeType.ALL)
private List<Board> boardList = new ArrayList<>();

 

위처럼 cascade를 부여하게 되면 자식 태그들은 삭제되게 된다. 따라서 cascade옵션은 유의해서 작성할 필요가 있다. 

 

 

2. is_deleted = true 인 경우를 조회하고싶은 경우 

@where에 작성한 내용이  기본으로 들어가기 때문에 is_deleted = true 인 값을 조회할때 조회가 되지 않는다. 따라서 이를 해결하려면 다음과 같다. 

 

JPA native query로 해결하기

@Query(value = "SELECT m.* FROM member m WHERE m.is_deleted = true", nativeQuery = true)
List<Member> findByMember();

 

위처럼 JPA respository에 native query를 사용해서 명시적으로 is_deleted = true 인 경우를 가져오면 된다. 

 

 

 

 

 

반응형

'Java > jpa' 카테고리의 다른 글

Jpa query method 사용하기  (0) 2020.03.15