Spring Batch 수행 시
Batch execution returned invalid results. Expected 1 but number of BatchResult objects returned was 2 오류가 발생하는 경우에 다음과 같이 조치한다.
■ 원인
하나의 Job에 Multi Step을 정의하고, ItemReader에서 MyBatisPagingItemReader ItemProcessor에서 Dao를 이용하여 DB에서 Insert 한 후 ItemWriter에서 MyBatisBatchItemWriter를 적용하는 경우에 발생함
하나의 Job에 단일 Step이 있는 경우에는 오류가 발생하지 않는다.
■ 오류 내역
09:11:40.975 [main] DEBUG o.s.transaction.support.TransactionTemplate | Initiating transaction rollback on application exception org.springframework.dao.InvalidDataAccessResourceUsageException: Batch execution returned invalid results. Expected 1 but number of BatchResult objects returned was 2 at org.mybatis.spring.batch.MyBatisBatchItemWriter.write(MyBatisBatchItemWriter.java:136) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) at com.sun.proxy.$Proxy14.write(Unknown Source) at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:175) at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:151) at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:274) at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:199) at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:75) at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406) at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:330) at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:271) at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:81) at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:374) at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144) at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:257) at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:200) at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64) at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67) at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169) at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144) at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:134) at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:306) at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135) at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128) at cmn.util.spring.batch.runner.BaseCmdRunner.start(BaseCmdRunner.java:278) at sehati.batch.sample.runner.SampleDB2FileJobRunner.main(SampleDB2FileJobRunner.java:162) |
■ MyBatisBatchItemWriter Code
MyBatisBatchItemWriter Class의 136라인에 result Size를 Check하는 로직이 들어있다.
result.size() 가 1 이 아닌 경우 Exception을 Throw하고 있다.
if (assertUpdates) { if (results.size() != 1) { throw new InvalidDataAccessResourceUsageException("Batch execution returned invalid results. " + "Expected 1 but number of BatchResult objects returned was " + results.size()); } |
■ 해결방법
<bean id="stepWriter1" class="org.mybatis.spring.batch.MyBatisBatchItemWriter" scope="step"> <property name="sqlSessionFactory" ref="sqlSession" /> <property name="statementId" value="batch.sample.Message.insMessage1" /> <property name="assertUpdates" value="false" /> </bean> |
MyBatisItemWriter의 속성 assertUpdates를 false로 하면 오류없이 정상적으로 처리된다.
'Spring Framrwork' 카테고리의 다른 글
spring framework interceptor (0) | 2018.03.02 |
---|---|
Google Map javascript API 사용법 (0) | 2018.02.07 |
C3 Bar Chart (0) | 2018.02.05 |
Spring Batch 모니터링 SQL (0) | 2018.02.03 |
Solve the Cross Domain issue with JSP (0) | 2018.02.02 |