I am using spring batch 5 using oracle. I have more than 15 batches running using the database. But it shows below error:
error code [8177]; ORA-08177: can't serialize access for this transaction
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [INSERT INTO BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION)
VALUES (?, ?, ?, ?)
]; SQL state [72000]; error code [8177]; ORA-08177: can't serialize access for this transaction
at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1573)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:667)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:960)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:1015)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:1020)
at org.springframework.batch.core.repository.dao.JdbcJobInstanceDao.createJobInstance(JdbcJobInstanceDao.java:157)
at org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:169)
at jdk.internal.reflect.GeneratedMethodAccessor32.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean.lambda$getObject$0(AbstractJobRepositoryFactoryBean.java:204)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244)
at jdk.proxy2/jdk.proxy2.$Proxy124.createJobExecution(Unknown Source)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:145)
at org.springframework.batch.core.launch.support.TaskExecutorJobLauncher.run(TaskExecutorJobLauncher.java:59)
at com.citylive.prepaidcard.config.ScheduledJobBean.perform(ScheduledJobBean.java:62)
at jdk.internal.reflect.GeneratedMethodAccessor36.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:96)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.sql.SQLException: ORA-08177: can't serialize access for this transaction
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:629)
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:563)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1150)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:770)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:298)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:497)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:151)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1051)
at oracle.jdbc.driver.OracleStatement.executeSQLStatement(OracleStatement.java:1530)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1310)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3745)
at oracle.jdbc.driver.OraclePreparedStatement.executeLargeUpdate(OraclePreparedStatement.java:3917)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3896)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:991)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
at org.springframework.jdbc.core.JdbcTemplate.lambda$update$2(JdbcTemplate.java:965)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:648)
... 34 more
Caused by: Error : 8177, Position : 0, Sql = INSERT INTO BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION)
VALUES (:1 , :2 , :3 , :4 )
, OriginalSql = INSERT INTO BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION)
VALUES (?, ?, ?, ?)
, Error Msg = ORA-08177: can't serialize access for this transaction
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:636)
... 51 more
Here is my code:
My application.properties:
spring.datasource.url=jdbc:oracle:thin:@localhost:1521/mydb spring.datasource.username=test spring.datasource.password=test124 db.name=test spring.datasource.driver-class-name=oracle.jdbc.OracleDriver spring.datasource.hikari.maximumPoolSize=10 spring.batch.jdbc.initialize-schema=always
My Schedule Run the job:
@Component @Slf4j public class MyJobJob { @Autowired JobLauncher jobLauncher; @Autowired EftJob2 eftJob; @Autowired private JobRepository jobRepository; @Scheduled(cron = "0 */2 * * * ?") public void perform() throws Exception { JobExecution execution = null; JobExecution lastJobExecutionStep1 = jobRepository.getLastJobExecution("EFT-STEP1", new JobParametersBuilder().toJobParameters()); if (lastJobExecutionStep1 == null || lastJobExecutionStep1.getStatus().isLessThan(BatchStatus.STARTING)) { log.info( "{} batch step1 {} execution {} Started: "); try { JobParameters jobParameters = new JobParametersBuilder() .addLong("startAtEftStep1", System.currentTimeMillis()) .toJobParameters(); execution = jobLauncher.run(eftJob.createEft(), jobParameters); log.info(" batch {} Step1 existStatus: "+execution.getExitStatus().getExitCode()); } catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException | JobParametersInvalidException ex) { log.error("batch {} Step1 {} execution {} JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException | JobParametersInvalidException message: "+ex.getMessage()); ex.printStackTrace(); }catch (Exception ex) { ex.printStackTrace(); } }else{ log.info(" batch step1 {} execution {} isRunning: "); } } }
Job:
@Component @RequiredArgsConstructor @Slf4j public class EftJob2 { private final MySummaryRepo approvedTrxSummaryRepo; private final MyTransactionRepo corpApprovedTransactionRepo; private final EftProcessorStep1 batchProcessorStep1; private final EftWriterStep1 batchWriterStep1; private final PlatformTransactionManager transactionManager; private final JobRepository jobRepository; @Autowired private JobExecutionListenerStep1 jobExecutionListenerStep1; @Autowired private MySPcall transactionSPcall; public Job createEft(){ return new JobBuilder("EFT-STEP1", jobRepository) .incrementer(new RunIdIncrementer()) .start(step1()) .build(); } private Step step1(){ return new StepBuilder("step1", jobRepository) .<ApprovedTrxSummery, ApprovedTrxSummery> chunk(10, transactionManager) .reader(new EftReaderStep1(approvedTrxSummaryRepo,corpApprovedTransactionRepo, transactionSPcall)) .processor(batchProcessorStep1) .writer(batchWriterStep1) .build(); } }
Batch config:
@Configuration public class BatchBean { @Bean public EftProcessorStep1 batchProcessorStep1() { return new EftProcessorStep1(); } @Bean public EftWriterStep1 batchWriterStep1() { return new EftWriterStep1(); } }
Repository:
@Transactional @Repository public interface TransactionRepo extends JpaRepository<TransactionEntity, Long> { @Query(value = "SELECT * FROM TRANSACTION WHERE STATUS =1 FOR UPDATE ", nativeQuery = true) List<TransactionEntity> getbKashTransaction(); }
Batch Reader: Read data from repository using ItemReader
@Slf4j public class ReaderStep1 implements ItemReader<TransactionEntity> { private Iterator<TransactionEntity> iterator; private TransactionSPcall transactionSPcall; public ReaderStep1(TransactionRepo transactionRepo, TransactionSPcall transactionSPcall) { this.transactionSPcall = transactionSPcall; List<TransactionEntity> list = transactionRepo.getbKashTransaction(); if(!list.isEmpty()){ this.iterator = list.iterator(); } } @Override public TransactionEntity read() { return (iterator != null && iterator.hasNext()) ? iterator.next() : null; } }
Batch Processor:
@Slf4j public class ProcessorStep1 implements ItemProcessor<TransactionEntity, TransactionEntity> { @Override public TransactionEntity process(TransactionEntity item) throws Exception { // Logic calling api return item; }
Batch writer:
@Slf4j public class WriterStep1 implements ItemWriter<TransactionEntity> { @Override public void write(Chunk<? extends TransactionEntity> chunk) { chunk.forEach(item -> { // update database }); } } }
It often occur the error.
What is the wrong of my code?
Please help