[JPA] Querydsl 벌크삭제
Querydsl 을 사용해서 벌크삭제를 해봤다.
아래와 같은 세개의 엔티티 클래스가 있다면,
' User ' , ' Order ', ' Post '
=> 각 User는 여러 Order를 가질 수 있고, 또한 여러 Post를 가질 수 있음.
User 엔티티 삭제로직을 처음에는 아래처럼 만들었다.
(User의 pk가 'userId'와 'userCode'라고 가정. 세세한 로직은 생략.)
if (!deleteList.isEmpty()) {
List<User> delList = new ArrayList<>();
for (Map<String, Object> del : deleteList) {
String userId = String.valueOf(del.get("userId"));
String userCode = String.valueOf(del.get("userCode"));
// 생략
User user = new User();
user.setUserId(userId);
user.setUserCode(userCode);
delList.add(user);
}
userRepository.deleteAll(delList);
}
=> 만일 삭제할 리스트(deleteList)가 있다면
for문으로 llist의 각각의 요소에 대한 entity를 생성 & deList에 담기 => deleteAll 메소드 실행.
* deleteAll 은 삭제할 엔티티의 수만큼 delete 쿼리를 실행.
문제점은 ' Order ', ' Post ' 에서 해당하는 엔티티들의 삭제였다.
각각 oneToMany 관계이기 때문에
삭제하는 user의 정보가 하나여도 order는 수십개가 될 수 있고,
user의 정보가 여러개라면 order의 갯수는그만큼 더 많아진다. (post도 마찬가지)
전부 for문을 돌리기엔 비효율적인 것 같아서 querydsl을 사용해봄.
import com.querydsl.jpa.impl.JPAQueryFactory;
(delUserList는 삭제할 userId들의 List라고 가정. 세세한 로직은 생략.)
// param => String userCode, List<Map<String, Object>> deleteList, List<String> delIdList
if(!deleteList.isEmpty() && !delIdList.isEmpty()){
// 생략
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QUser user = QUser.user;
long delUserCount = queryFactory.delete(user)
.where(user.userCode.eq(userCode)
.and(user.userId.in(delIdList)))
.execute();
if(delUserCount == delIdList.size()){
QOrder order = QOrder.order;
queryFactory.delete(order)
.where(order.userCode.eq(userCode)
.and(order.userId.in(delIdList)))
.execute();
QPost post = QPost.post;
queryFactory.delete(post)
.where(post.userCode.eq(userCode)
.and(post.userId.in(delIdList)))
.execute();
} else {
throw new RuntimeException("err");
}
}
쿼리로 조건에 해당하는 entity들을 한꺼번에 삭제!!
=> querydsl은 삭제완료된 row의 갯수를 반환!! (Long타입)
@Transactional로 관리하고 있지만 'delUserCount' 로 한번더 체크해줬다.
.execute() 메소드 : 이 메소드를 호출할 때 쿼리가 삭제됨.
이 방식이 맞는지는 모르겠다. 더 좋은 방법을 찾으면 계속해서 수정해나갈 예정.
++ 공통로직으로 분리해봄.
[JPA] Querydsl 벌크삭제 (2)
테이블의 데이터들이 다대다 관계로 구성되어 있고 하나의 데이터를 삭제할 때 관련된 모든 테이블의 데이터를 삭제하기 위해 QueryDSL 공통로직 생성. (이전방식) 서비스 로직에서 엔티티별 Q
phyho.tistory.com