StravaService.getRide() 메소드는 List<Ride> 오브젝트를 리턴하기도 하지만 내부에서 RideRepository.saveAll(list)를 호출하면서 Ride 엔티티들을 DB에 저장한다.

지금 테스트로 사용하는 계정의 경우에 약 900개의 Ride 데이터를 가지고있는데 기본적으로 JPA의 saveAll() 메소드는 내부에서 save() 메소드를 여러번 for문을 돌면서 호출하는것으로 구현되어있다.

따라서 각 Ride 엔티티마다 save() 메소드를 호출한것과 동일한 효과를 가지며 900개의 SQL이 발생한다는 것이다.

이를 해결하기 위해서 JPA는 bulk insert라는 여러개의 데이터를 하나의 커넥션으로 insert할 수 있는 기능을 제공한다.

하지만 본 시스템에서 사용하고 있는 mysql에서는 이를 활용하기가 어렵다.

기본적으로 Mysql은 @GeneratedValue stratagey.IDENTITY라는 데이터를 DB에 실제로 저장하면서 ID를 배정하는 방식을 사용하는데 bulk insert로 여러개의 엔티티를 동시에 저장하게 될 경우 ID를 배정하기가 어려워지기 때문이다.

따라서 mysql에서 Bulk insert를 사용하고자 한다면 JDBC를 직접 사용하는 수 밖에는 없다.

RideBatchRepository는 내부에서 JDBC Template를 사용해 bulk insert를 구현했다. 이제 StravaService.getRide() 내부에서 RideBatchRepository.saveAll() 을 호출하여 많은 양의 Ride 엔티티를 한번의 커넥션으로 저장할 수 있게 되었다.

이때 여기서 발생한 한가지 문제점이 있다.

stravaService.getRide()를 호출하는 UserService.addUser()의 상단에는 @Transactional이 붙어있다.

이는 복잡한 로직을 가지는 addUser() 메소드가 모종의 이유로 예외가 발생해 정상적으로 데이터가 DB에 저장되지 않는것을 방지하기 위해 예외가 발생한 경우 메소드 내에서 수행한 모든 DB 작업을 롤백하기 위해서 설정한 것이다.

JPA는 영속성 컨텍스트를 운영하면서 repository.save()를 통해 엔티티를 영속화 하더라도 즉시 DB에 반영하는 것이 아니라 영속성 컨텍스트 내의 쓰기 지연 저장소에 보관한다.