아키텍처와 함께

블로그 이미지
by gregorio
  • Total hit
  • Today hit
  • Yesterday hit

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
AND

ARTICLE CATEGORY

분류 전체보기 (56)
Spring Framrwork (33)
Linux (1)
APM (1)
Java (8)
python (0)
ant (1)
chart (1)
OS (1)
tomcat (1)
apache (1)
database (0)

RECENT ARTICLE

RECENT COMMENT

CALENDAR

«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

ARCHIVE

LINK