본문 바로가기
  • Where there is a will there is a way.
개발/spring

JPA delete 방법과 심화 delete All transactional 문제

by 소확행개발자 2020. 2. 15.

 

우선 jpa delete 에 대해서 알아보자

delete mapping /{cartId} 로 단일건도 되지만

아무리 생각해봐도 for 문을 돌리면서 클라이언트가 돌리든 서버가 돌리든 .. 비효율일 것 같다는 생각이 들었다. 그래서 찾아본 결과

다음과 같이 list param 으로 사용해도 될것같다는 판단이 들었다.

list param 은 콤마로 구분해도 되고, 클라이언트에서 form 으로 전달해도 된다고 한다.

 @DeleteMapping("/{memberId}/cart")
    public ResponseEntity<ApiResponse> deleteCart(@PathVariable(name = "memberId") long memberId,
            @RequestParam(value = "cartIds") List<Long> cartIds) {

        cartService.deleteCart(memberId, cartIds);

        return ApiResponseFactory
                .createSuccessResponse();
    }

 

entity 는 Cart 와 CartOption  이 N+1 로 되어있다고 해보자.

public class Cart {

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

    @Column(name = "mem_idx")
    private Long memberId;

    // delete 할때 부모를 지우면 자식도 같이 지워야하기 때문에 cascadeType all 로 했다.
    @OneToMany(mappedBy = "cart", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JsonIgnore
    private List<CartOption> cartOptions;

다음은 카트를 지우는 method 이다.

@Transactional
public void deleteCart(long memberId, List<Long> cartIds) throws CartValidException {

        long deleteCount = cartRepository.deleteAllByMemberIdAndIdIn(memberId, cartIds);

        // 해당 멤버로 cart 지울게 없는 경우는 잘못들어온 경우이다.
        if(deleteCount == 0) {
            throw new CartValidException("invalid member");
        }


    }
public interface CartRepository extends JpaRepository<Cart, Long> {

    long deleteAllByMemberIdAndIdIn(long memberId, List<Long> cartIds);
}

이렇게 하고 jpa cartId 2개를 삭제요청해보면 쿼리는 다음과 같다. 

select cart0_.cart_idx                 as cart_idx1_1_,
  
from cart_base cart0_
where cart0_.mem_idx = ?
  and (cart0_.cart_idx in (?, ?));
select cartoption0_.cart_idx        as cart_idx8_2_0_,
       cartoption0_.cart_option_idx as cart_opt1_2_0_,
   
from cart_option cartoption0_
where cartoption0_.cart_idx = ?;
select cartoption0_.cart_idx        as cart_idx8_2_0_,
     
from cart_option cartoption0_
where cartoption0_.cart_idx = ?;
delete
from cart_option
where cart_option_idx = ?;
delete
from cart_option
where cart_option_idx = ?;
delete
from cart_base
where cart_idx = ?;
delete
from cart_option
where cart_option_idx = ?;
delete
from cart_base
where cart_idx = ?;

 

2 번 + N 번으로 조회쿼리가 날라간 후에 각 delete 를 한다.

( cart 와 option ) 연관관계 때문에

 

만약 대량의 데이터를 삭제해야하는 경우라면 ?

해당방법을 사용하면 안된다. 하나의 컬럼당 n+1 쿼리가 날라갈테니까

 

그럴때는 @Query 로 한꺼번에 지우길 권장함

 

 

'개발 > spring' 카테고리의 다른 글

JPA 애플리케이션 영속성 관리  (0) 2020.04.13
JPA 연관관계  (0) 2020.03.16
스프링 DI  (0) 2020.02.09
싱글톤 패턴의 한계와 스프링 싱글톤  (0) 2020.02.09
스프링 application context  (0) 2020.02.08

댓글