문제 상황
대량의 데이터를 insert 하는 로직이 있었는데, 계속 데이터 일부분이 누락되는 현상이 발생 하였다.
총 400row가 insert 되어야 하는데, 380개 정도만 insert 되는 식이었다.
내가 insert하는 방식은 아래와 같았다.
public Flux<TestDTO> setDatas(List<TestDTO> dataList){
repository.saveAll(dataList);
}
repository는 아래처럼 R2DBC Repository를 상속받아 사용하였다.
public interface TestRepository extends R2dbcRepository<TestDTo, String>
해결 방법
기존의 Iterable을 바로 인자로 넘기는 방법에서, 아래처럼 Flux형태로 바꾸어 saveAll 하는 방식으로 바꾸니 정상적으로 작동함을 볼 수 있었다.
public Flux<TestDTO> setDatas(List<TestDTO> dataList){
repository.saveAll(Flux.fromIterable(dataList));
}
여러번 테스트를 했지만, 용량이 큰 데이터들이 모두 다 insert 되는 것을 확인 할 수 있었다.
사실 지금까지 Iterable 형태로 받아오면 그냥 saveAll(Iterable), Flux 형태로 받는다면 saveAll(Publisher) 형태로 이용했다.
결론적으로 이번 경험을 통해서 앞으로는 항상 saveAll(Publisher) 메소드를 사용하려고 한다.
의문점
사실 완벽히 풀리지 않은 의문점이 있다.
SimpleR2dbcRepository를 보면 아래처럼, 결국 같은 로직이 아닌가 하는 생각이 들기 때문이다.
@Override
@Transactional
public <S extends T> Flux<S> saveAll(Iterable<S> objectsToSave) {
Assert.notNull(objectsToSave, "Objects to save must not be null");
return Flux.fromIterable(objectsToSave).concatMap(this::save);
}
@Override
@Transactional
public <S extends T> Flux<S> saveAll(Publisher<S> objectsToSave) {
Assert.notNull(objectsToSave, "Object publisher must not be null");
return Flux.from(objectsToSave).concatMap(this::save);
}
그리고, 우리가 일반적으로 아는 bulk insert 방식이 아니라 왜 하나하나 save 쿼리를 날리는 것인지...
이 부분에 대해서는 추후 다시 정리하도록 하겠다.