본문 바로가기

JAVA/JPA

[JPA] Spring JPA - deleteAll() vs deleteAllInBatch() vs @Query 사용 및 차이점

 

 

사실 실무에서는 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