사실 실무에서는 DB 데이터 삭제는 잘 안 한다.
그래도 필요한 경우가 있긴 하다.
1. DeleteAll()
/*
* (non-Javadoc)
* @see org.springframework.data.repository.Repository#deleteAll()
*/
@Override
@Transactional
public void deleteAll() {
for (T element : findAll()) {
delete(element);
}
}
DB를 조회해서 1개씩 Delete 한다.
만약에 1000개의 데이터를 삭제해야 된다면 1000번 실행이 된다.
굉장히 비효휼적이고 낭비이다.
DeleteAllInBatch() 를 사용하는 것을 추천한다.
2. DeleteAllInBatch()
/*
* (non-Javadoc)
* @see org.springframework.data.jpa.repository.JpaRepository#deleteInBatch(java.lang.Iterable)
*/
@Override
@Transactional
public void deleteAllInBatch(Iterable<T> entities) {
Assert.notNull(entities, "Entities must not be null!");
if (!entities.iterator().hasNext()) {
return;
}
applyAndBind(getQueryString(DELETE_ALL_QUERY_STRING, entityInformation.getEntityName()), entities, em)
.executeUpdate();
}
deleteAllInBatch()는 QueryUtils - applyAndBind를 사용한다.
getQueryString()의 매개변수인 DELETE_ALL_QUERY_STRING 을 받는다.
//QueryUtils 의 매개변수 3개.
public abstract class QueryUtils {
public static final String COUNT_QUERY_STRING = "select count(%s) from %s x";
public static final String DELETE_ALL_QUERY_STRING = "delete from %s x";
public static final String DELETE_ALL_QUERY_BY_ID_STRING = "delete from %s x where %s in :ids";
}
DELETE_ALL_QUERY_STRING 쿼리를 보면 delete from %s x 라고 작성되어 있다.
= delete from 테이블 명.
public abstract class QueryUtils {
public static <T> Query applyAndBind(String queryString, Iterable<T> entities, EntityManager entityManager) {
Iterator<T> iterator = entities.iterator();
StringBuilder builder = new StringBuilder(queryString);
builder.append(" where");
int i = 0;
while (iterator.hasNext()) {
iterator.next();
builder.append(String.format(" %s = ?%d", alias, ++i));
if (iterator.hasNext()) {
builder.append(" or");
}
}
Query query = entityManager.createQuery(builder.toString());
return query;
}
}
List<Sample> list = repository.findBySampleId(Sample);
repository.deleteAllInBatch(list);
해당 쿼리를 통해 한 번에 제거는 되지만,
QueryUtils 의 applyAndBind를 보면 where 조건에 or 로 이어붙이고 있는 걸 볼 수 있다.
DeleteAllInBatch() 는 EntityManager 의 createQuery() 로 쿼리를 생성하고 excuteUpdate() 를 호출하여
한 번의 쿼리로 삭제를 진행한다.
3. @Query - repository
@Transactional
@Modifying
@Query(nativeQuery = true, value = "delete from sample s where s.sample_Id=:sampleId")
void deleteAllBySampleId(@Param("sampleId") String sampleId);
or 대신 in 절을 사용하여 한 번에 제거한다.
많은 양의 데이터를 조회하는 경우 or 절을 연속적으로 사용하는 것 보다 훨씬 효율적이다.
or 절은 ALL , in 절은 range를 탄다.
쿼리는 최대한 한 번에 실행하는 것이 좋다.
데이터가 많아질수록 성능 차이가 크다.
deleteAll() 과 deleteAllInBatch() 는 인자로 아무것도 넘겨주지 않으면 해당 테이블의 데이터를 전체 삭제 한다.
+
매개변수(Parameter)와 인자(Argument).
매개변수는 함수를 정의할 때 사용되는 변수(미지수)를 의미 한다.
인자는 실제로 함수가 호출될 때 넘기는 값을 의미한다.
ex) getQueryString(String sample)라는 함수를 정의할 때 여기서 sample은 매개변수이고,
실제로 사용할 때 getQueryString("sample")에서 "sample"은 인자이다.
Reference
https://yeonyeon.tistory.com/286
[JPA] delete문이 N개가 발생한다고요?😱
💥 원인 발생 현재 진행중인 프로젝트에서 deleteAllByXXX를 호출하자 delete가 N개 나가는 현상이 발생했다. 왜 여러개가 나갈까? 왜 한번에 삭제되지 않는걸까?를 찾아보게 되었다. 📝 원인 분석 del
yeonyeon.tistory.com
'JAVA > JPA' 카테고리의 다른 글
[JPA] Entity PK 복합키 사용 - 직렬화 (0) | 2023.01.02 |
---|