우선 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 |
댓글