在获取所有数据之前,Spring Batch ResultSet 已被其他人关闭

Posted

技术标签:

【中文标题】在获取所有数据之前,Spring Batch ResultSet 已被其他人关闭【英文标题】:Spring Batch ResultSet got closed by other before all data being fetched 【发布时间】:2016-03-28 02:08:48 【问题描述】:

我正在尝试将 DB2 源设置为 Batch 元数据的持久性。我得到了这个堆栈跟踪:

Caused by: org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, CREATE_TIME, LAST_UPDATED, VERSION, JOB_CONFIGURATION_LOCATION from rhall.BATCH_JOB_EXECUTION where JOB_INSTANCE_ID = ? order by JOB_EXECUTION_ID desc]; SQL state [null]; error code [-4470]; [jcc][t4][10120][10898][3.57.82] Invalid operation: result set is closed. ERRORCODE=-4470, SQLSTATE=null; nested exception is com.ibm.db2.jcc.am.SqlException: [jcc][t4][10120][10898][3.57.82] Invalid operation: result set is closed. ERRORCODE=-4470, SQLSTATE=null
   at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:84)
   at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
   at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
   at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:645)
   at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:680)
   at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:712)
   at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:722)
   at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:777)
   at org.springframework.batch.core.repository.dao.JdbcJobExecutionDao.findJobExecutions(JdbcJobExecutionDao.java:131)
   at org.springframework.batch.core.repository.support.SimpleJobRepository.getStepExecutionCount(SimpleJobRepository.java:253)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
   at java.lang.reflect.Method.invoke(Method.java:611)
   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.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
   at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
   at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
   at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
   at $Proxy32.getStepExecutionCount(Unknown Source)
   at org.springframework.batch.core.job.flow.JobFlowExecutor.isStepRestart(JobFlowExecutor.java:82)
   at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:63)
   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) ... 22 more
Caused by: com.ibm.db2.jcc.am.SqlException: [jcc][t4][10120][10898][3.57.82] Invalid operation: result set is closed. ERRORCODE=-4470, SQLSTATE=null
   at com.ibm.db2.jcc.am.bd.a(bd.java:660)
   at com.ibm.db2.jcc.am.bd.a(bd.java:60)
   at com.ibm.db2.jcc.am.bd.a(bd.java:103)
   at com.ibm.db2.jcc.am.zl.Db(zl.java:4219)
   at com.ibm.db2.jcc.am.zl.q(zl.java:4180)
   at com.ibm.db2.jcc.am.zl.c(zl.java:1009)
   at com.ibm.db2.jcc.am.zl.getTimestamp(zl.java:985)
   at com.ibm.ws.rsadapter.jdbc.WSJdbcResultSet.getTimestamp(WSJdbcResultSet.java:2607)
   at org.springframework.batch.core.repository.dao.JdbcJobExecutionDao$JobExecutionRowMapper.mapRow(JdbcJobExecutionDao.java:425)
   at org.springframework.batch.core.repository.dao.JdbcJobExecutionDao$JobExecutionRowMapper.mapRow(JdbcJobExecutionDao.java:396)
   at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:93)
   at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:60)
   at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:693)
   at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:629) 
  ... 45 more 

我跟踪代码,发现这个方法的问题:JdbcJobExecutionDao.mapRow(ResultSet rs, int rowNum)

(我使用的是 Spring-batch 版本 3.0.6)列出在此处粘贴该方法以供您使用 方便,

public JobExecution mapRow(ResultSet rs, int rowNum)
 throws SQLException           
 Long id = rs.getLong(1);           
 String jobConfigurationLocation = rs.getString(10);            
 JobExecution jobExecution;             
 if (jobParameters == null) 
    jobParameters = getJobParameters(id);           
 
 if (jobInstance == null) 
    jobExecution = new JobExecution(id, jobParameters, jobConfigurationLocation);           
  else 
    jobExecution = new JobExecution(jobInstance, id, jobParameters, jobConfigurationLocation);          
 
 jobExecution.setStartTime(rs.getTimestamp(2));
 jobExecution.setEndTime(rs.getTimestamp(3));
 jobExecution.setStatus(BatchStatus.valueOf(rs.getString(4)));
 jobExecution.setExitStatus(new ExitStatus(rs.getString(5), rs.getString(6)));             
 jobExecution.setCreateTime(rs.getTimestamp(7));
 jobExecution.setLastUpdated(rs.getTimestamp(8));
 jobExecution.setVersion(rs.getInt(9));          
 return jobExecution;        

当我跟踪它时,我注意到问题出在getJobParameters(id) 方法中。此方法对JOB_EXECUTION_PARAMS 表执行另一个查询,以获取给定作业 ID 的参数。但在此方法中,getConnection 方法返回与当前上下文中相同的连接。查询后,finally 块关闭resultSet。所以当控件回到mapRow 方法时,它在这一行失败了:

jobExecution.setStartTime(rs.getTimestamp(2));  

这是因为rs已经被getJobParameters(id)方法关闭了。

想知道我是否做错了?请指出我。 非常感谢。

【问题讨论】:

我有同样的问题并开始赏金... SQL状态 [55032];错误代码[-1224]; [jcc][t4][2055][14191][4.19.26] 数据库管理器无法接受新请求,已终止所有正在进行的请求,或由于在目标上检测到意外错误条件而终止了此特定请求系统。 ERRORCODE=-1224,SQLSTATE=55032 您的工作(服务或 DAO)中是否有标有 @Transactional 的代码? 【参考方案1】:

从我使用 Batch Infrastructure 类的方法中删除 @Transactional,即 JobExplorer,解决了封闭的 ResultSet 周围的问题。

【讨论】:

以上是关于在获取所有数据之前,Spring Batch ResultSet 已被其他人关闭的主要内容,如果未能解决你的问题,请参考以下文章

从DB2获取数据并使用没有元数据表的Spring Batch保存在MongoDB中

Spring Batch:ItemProcessor 不处理所有记录

Java spring boot + spring batch:处理大量信息

Spring Batch:在读写器之间传递数据

在 Spring Batch 步骤中移动 HashMap

在ChunkProcessorChunkHandler上找不到Spring Batch SpelEvaluationException方法