使用springBatch做批量处理
在write方法中,使用嵌套事务,因为write本身有事务所以又添加了嵌套事务 
异常提示:
DEBUG: org.springframework.jdbc.datasource.JdbcTransactionObjectSupport.releaseSavepoint(JdbcTransactionObjectSupport.java:145) - Could not explicitly release JDBC savepoint
java.sql.SQLException: 不支持的特性
at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:133)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:199)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:263)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:271)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:445)
at oracle.jdbc.driver.PhysicalConnection.releaseSavepoint(PhysicalConnection.java:5687)
at org.springframework.jdbc.datasource.JdbcTransactionObjectSupport.releaseSavepoint(JdbcTransactionObjectSupport.java:142)
at org.springframework.transaction.support.AbstractTransactionStatus.releaseSavepoint(AbstractTransactionStatus.java:197)
at net.etongbao.vasp.ac.batch.writer.AcWriter$1.doInTransaction(AcWriter.java:99)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at net.etongbao.vasp.ac.batch.writer.AcWriter.write(AcWriter.java:92)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:171)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:150)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:269)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:194)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:74)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:386)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:250)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)
at net.etongbao.vasp.ac.launcher.SpringBatchLanuncher.start(SpringBatchLanuncher.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:264)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:86)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:525)、
代码:@Override
public void write(List<? extends Map<String, Object>> bsList) { for (final Map<String, Object> shopMap : bsList) {
                    try{
// 设置为内嵌事务
transactionTemplate
.setPropagationBehavior(TransactionTemplate.PROPAGATION_NESTED);
transactionTemplate.execute(new TransactionCallback<Object>() {
public Object doInTransaction(
TransactionStatus ts) {
sendHandle.excute(shopMap);
return tscNo;
}
});
                          }
} catch (AcException e) {
LOG.error("交易参考号:{},账务处理出现异常", tscNo, e);
tscBaseDao.updateQuestionTsc(tscNo, e.getMessage());
} catch (RuntimeException e) {
LOG.error("交易参考号:{},账务处理出现异常", tscNo, e);
tscBaseDao.updateQuestionTsc(tscNo, e.getMessage());
}
}
LOG.debug("当前处理账务记录{}条", bsList.size());
}

解决方案 »

  1.   

    来自http://forum.springsource.org/showthread.php?18777-Could-not-explicitly-release-JDBC-savepointActually, the above is just a warning logged by Spring, not an actual error thrown. This can usually safely be ignored.
    Oracle doesn't support explicit "releaseSavepoint" calls, for whatever reason. Consequently, we try the call but catch and log any SQLException thrown, simly proceeding from there on.On that occasion, I've just degraded the log level used for that warning from INFO to DEBUG. Else it's gonna cause more confusion on Oracle, where it's gonna appear for every savepoint.