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() 메소드 : 이 메소드를 호출할 때 쿼리가 삭제됨.
이 방식이 맞는지는 모르겠다. 더 좋은 방법을 찾으면 계속해서 수정해나갈 예정.
++ 공통로직으로 분리해봄.
'Java > JPA' 카테고리의 다른 글
[JPA] findBy~ 일부 필드값만 가져오기 (JPQL, 네이티브쿼리) / (+ 오류) (0) | 2024.07.28 |
---|---|
[JPA] JPA_existBy~ / Querydsl 성능비교 (+ fetchOne(), fetchFirst()) (0) | 2024.06.21 |
[JPA] List<Entity> 비교 (0) | 2024.06.19 |
[JPA] findById, existsById, getById (0) | 2024.06.19 |
[Java/Spring] JPA / JPA 어노테이션 / JpaRepository 인터페이스 (0) | 2024.03.23 |