인프런 커뮤니티 질문&답변

myeonjeong님의 프로필 이미지

작성한 질문수

스프링 배치

JdbcBatchItemWriter Query

해결된 질문

23.03.18 10:31 작성

·

1.1K

0

안녕하세요 선생님!

JdbcBatchItemWriter 에서 발생하는 Query 가

batch query 로 나가지 않는 것 같아서 질문 드립니다!

 

혹시 jdbc 에서 batch query 로 보내더라도 optimizer 에 의해

단일쿼리로 변경되어서 나갈수도 있나요?!

 

감사합니다.

 

위 사진은 MySQL 의 Query Log 입니다.

 

제 설정은 아래와 같습니다

@Configuration
class HelloJobConfiguration(
    private val jobBuilderFactory: JobBuilderFactory,
    private val stepBuilderFactory: StepBuilderFactory,
    private val dataSource: DataSource,
) {

    @Bean
    fun job(): Job {
        return jobBuilderFactory.get("job")
            .incrementer(RunIdIncrementer())
            .start(step1())
            .build()
    }

    @Bean
    fun step1(): Step {
        return stepBuilderFactory.get("step1")
            .chunk<Customer, Customer>(5)
            .reader(customItemReader())
            .writer(customItemWriter())
            .build()
    }

    @Bean
    fun customItemReader(): ItemReader<Customer> {
        return JdbcPagingItemReaderBuilder<Customer>()
            .name("jdbcPagingItemReader")
            .dataSource(dataSource)
            .pageSize(5)
            .rowMapper(BeanPropertyRowMapper(Customer::class.java))
            .queryProvider(queryProvider())
            .build()
    }

    @Bean
    fun queryProvider(): PagingQueryProvider {
        return SqlPagingQueryProviderFactoryBean().apply {
            setDataSource(dataSource)
            setSelectClause("SELECT id, firstName, lastName, birthdate")
            setFromClause("FROM customer")
            setSortKeys(mapOf("id" to Order.ASCENDING))
        }.`object`
    }

    @Bean
    fun customItemWriter(): ItemWriter<Customer> {
        return JdbcBatchItemWriterBuilder<Customer>()
            .dataSource(dataSource)
            .sql("INSERT INTO customer2 values(:id, :firstName, :lastName, :birthdate);")
            .beanMapped()
            .build()
    }
}

답변 1

1

정수원님의 프로필 이미지
정수원
지식공유자

2023. 03. 21. 17:28

쿼리가 콘솔에 나오더라도 내부적으로 배치 형태로 업데이트 된다 보시면 됩니다.

실제로 내부 소스를 보시면 jdbctemplate.batchupdate(query).... 와 같이 되어 있습니다.

if (usingNamedParameters) {
   if(items.get(0) instanceof Map && this.itemSqlParameterSourceProvider == null) {
      updateCounts = namedParameterJdbcTemplate.batchUpdate(sql, items.toArray(new Map[items.size()]));
   } else {
      SqlParameterSource[] batchArgs = new SqlParameterSource[items.size()];
      int i = 0;
      for (T item : items) {
         batchArgs[i++] = itemSqlParameterSourceProvider.createSqlParameterSource(item);
      }
      updateCounts = namedParameterJdbcTemplate.batchUpdate(sql, batchArgs);
   }
}
else {
   updateCounts = namedParameterJdbcTemplate.getJdbcOperations().execute(sql, new PreparedStatementCallback<int[]>() {
      @Override
      public int[] doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
         for (T item : items) {
            itemPreparedStatementSetter.setValues(item, ps);
            ps.addBatch();
         }
         return ps.executeBatch();
      }
   });
}

보시면

namedParameterJdbcTemplate.batchUpdate(sql, batchArgs)
ps.addBatch();
ps.executeBatch()

와 같이 되어 있습니다.