결론적으로 @Bean 어노테이션이 없어서 발생한 상황이다.
JdbcBatchItemWriter 사용할 땐 @Bean 이 꼭 필요하다.
왜냐면 Spring의 Bean 생명주기와 초기화 과정에서의 차이가 발생하기 때문.
원본 소스코드와 함께 어떤 차이가 발생하는지 보자.
itemPreparedStatementSetter를 찾을건지, NamedParameter를 찾을건지
"usingNamedParemeter" 라는 변수로 나뉜다.
원본 소스코드:
// JdbcBatchItemWriter.java
@Override
public void write(final List<? extends T> items) throws Exception {
if (!items.isEmpty()) {
if (logger.isDebugEnabled()) {
logger.debug("Executing batch with " + items.size() + " items.");
}
// usingNamedParameters 체크하는 핵심 부분
if (this.usingNamedParameters) {
executeWithNamedParameters(items);
}
else {
executeWithPreparedStatements(items);
}
}
}
1. @Bean 있는 경우:
- Spring Container가 Bean을 생성하고 초기화할 때 afterPropertiesSet() 메서드를 자동으로 호출합니다
- 이 때 내부적으로 SQL 문을 파싱하고 Named Parameter 사용 여부를 자동으로 감지합니다
- 결과적으로 SQL에 :paramName 형태가 있다면 usingNamedParameters가 true로 설정됩니다
2. @Bean 없는 경우:
- Bean 생명주기를 거치지 않아 afterPropertiesSet()이 자동으로 호출되지 않습니다
- SQL 파싱과 Named Parameter 감지가 이루어지지 않습니다
- 기본값인 false가 유지됩니다
afterPropertiesSet() 함수의 코드:
// JdbcBatchItemWriter.java
@Override
public void afterPropertiesSet() {
Assert.notNull(this.namedParameterJdbcTemplate, "A DataSource or a NamedParameterJdbcTemplate is required.");
Assert.notNull(this.sql, "An SQL statement is required.");
Assert.notNull(this.itemPreparedStatementSetter, "An ItemPreparedStatementSetter or an ItemSqlParameterSourceProvider is required.");
if (this.itemSqlParameterSourceProvider != null) {
// SQL이 Named Parameters를 포함하는지 분석
this.usingNamedParameters = true;
// SQL 파싱하여 PreparedStatement에 필요한 파라미터 정보 추출
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(this.sql);
this.insertTypes = new int[parsedSql.getTotalParameterCount()];
}
}
@Bean 이 절대 쓰기 싫으면 별도로 afterPropertiesSet() 함수를 호출해줘도 잘 작동한다.
JdbcBatchItemWriter<MyDTO> writer = new JdbcBatchItemWriterBuilder<MyDTO>()
.dataSource(dataSource) // 1. 데이터소스 설정
.sql("INSERT INTO table VALUES (:val)") // 2. SQL 설정
.beanMapped() // 3. 파라미터 프로바이더 설정
.build(); // 4. 객체 생성
writer.afterPropertiesSet(); // 5. 초기화 수행
반응형
'개발 > java' 카테고리의 다른 글
중복 맞이 중복코드 최소화 (0) | 2024.07.25 |
---|---|
Spring Batch + MSSQL 실행과정 FLOW 파헤치기, meta db 접근순서 (3) | 2024.04.29 |
build.gradle, settings.gradle, properties 차이? 역할? 알아보기 (0) | 2024.04.16 |
Spring Actuator 로 Custom Endpoint 등록 및 변수 전달 (0) | 2024.03.19 |
포장을 못하면 개발을 못해요 (API 유지보수성 극대화) (0) | 2021.06.10 |