> Step,Spring Batch Job Repository和业务仓库(使用各种数据源)都使用JTA事务管理器.
>步骤“myStep”使用Jdbc分页项阅读器.
> WebLogic,Oracle XE和/或EE
我想在“myStep”中分析Jdbc Cursor Item Reader的性能,但是在第一次提交之后,第二个块的第一次读取将会失败,并返回java.sql.sqlException:Result set已经关闭.
我怀疑JTA / XA驱动程序由于某种原因关闭游标,所以我给了“myStep”一个简单的数据源事务管理器(在读者使用的数据源上),并且该步骤能够成功完成.这不是一个解决方案,因为这样会破坏事件的完整性.
是否可以在JTA管理步骤中使用光标阅读器(使用下面描述的环境)?如果是这样,我的结局可能配置不正确?
环境
>事务管理器:< bean id =“myTransactionManager”
类= “的org.springframework.transaction.jta.JtaTransactionManager”/>
>数据源驱动程序:OracleXADataSource JDBC 6 11.1.0.7.0
> WebLogic:12.1.3.0.0
> Oracle DB 11g:企业版11.2.0.4.0
> OS:OSX或Linux
配置
<bean id="myTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
<bean id="myDataSource" class="org.springframework.jndi.Jndiobjectfactorybean">
<property name="jndiName" value="jdbc/myDataSource"/>
<property name="proxyInterface" value="javax.sql.DataSource"/>
</bean>
<batch:step id="myStep" job-repository="myJobRepositoryFactory">
<batch:tasklet transaction-manager="myTransactionManager">
<batch:chunk
reader="myReader"
processor="myProcessor"
writer="myWriter"
commit-interval="100"
processor-transactional="false"/>
<batch:listeners>
<batch:listener ref="myListener"/>
</batch:listeners>
</batch:tasklet>
</batch:step>
<bean id="myReader" class="org.springframework.batch.item.database.JdbcCursorItemReader" scope="step">
<property name="dataSource" ref="myDataSource"/>
<property name="sql" value="SELECT * FROM myHugeTable ORDER BY myColumn DESC"/>
<property name="rowMapper">
<bean class="myRowMapper"/>
</property>
</bean>
抓住了这个行为
以下是结果集的调用堆栈在下一个块的读取之前被关闭.注意XA连接关闭所有语句,这会导致JDBC关闭所有结果集.
java.lang.Thread.State: RUNNABLE at weblogic.jdbc.wrapper.ResultSet.internalClose(ResultSet.java:178) at weblogic.jdbc.wrapper.Statement.closeAllResultSets(Statement.java:286) at weblogic.jdbc.wrapper.Statement.internalClose(Statement.java:395) at weblogic.jdbc.wrapper.Statement.internalClose(Statement.java:367) at weblogic.jdbc.wrapper.XAConnection.closeAllStatements(XAConnection.java:393) at weblogic.jdbc.wrapper.XAConnection.cleanup(XAConnection.java:406) at weblogic.jdbc.wrapper.XAConnection.releasetoPool(XAConnection.java:432) at weblogic.jdbc.jta.DataSource.removeTxAssoc(DataSource.java:1907) at weblogic.jdbc.jta.DataSource.prepare(DataSource.java:1090) at weblogic.transaction.internal.XAServerResourceInfo.prepare(XAServerResourceInfo.java:1408) at weblogic.transaction.internal.XAServerResourceInfo.prepare(XAServerResourceInfo.java:522) at weblogic.transaction.internal.ServerSCInfo.startPrepare(ServerSCInfo.java:411) at weblogic.transaction.internal.ServerTransactionImpl.localPrepare(ServerTransactionImpl.java:2709) at weblogic.transaction.internal.ServerTransactionImpl.globalPrepare(ServerTransactionImpl.java:2340) at weblogic.transaction.internal.ServerTransactionImpl.internalCommit(ServerTransactionImpl.java:300) at weblogic.transaction.internal.ServerTransactionImpl.commit(ServerTransactionImpl.java:260) at org.glassfish.transaction.TransactionManagerImplCommon.commit(TransactionManagerImplCommon.java:571) at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1021) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:150) at org.springframework.batch.core.step.tasklet.taskletStep$2.doInChunkContext(taskletStep.java:271) at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77) at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368) 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:198) 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:165) 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:304) at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
解决方法
这是我们使用的XA / JTA配置.也许这对你有用:
@Bean(initMethod = "init",destroyMethod = "shutdownForce")
public UserTransactionService userTransactionService() {
return new UserTransactionServiceImp(userTransactionServiceProperties());
}
@Bean(initMethod = "init",destroyMethod = "close")
@DependsOn("userTransactionService")
public UserTransactionManager atomikosTransactionManager() {
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setForceShutdown(true);
userTransactionManager.setStartupTransactionService(false);
return userTransactionManager;
}
@Bean
@DependsOn("userTransactionService")
public UserTransaction atomikosUserTransaction() throws SystemException {
return new UserTransactionImp();
}
@Bean
@DependsOn("userTransactionService")
public JtaTransactionManager transactionManager() throws SystemException {
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
jtaTransactionManager.setTransactionManager(atomikosTransactionManager());
jtaTransactionManager.setUserTransaction(atomikosUserTransaction());
jtaTransactionManager.setAllowCustomIsolationLevels(true);
return jtaTransactionManager;
}
我们的所有数据源都被实例化为org.springframework.boot.jta.atomikos.AtomikosDataSourceBean.例如,Ora数据源被实例化为:
AtomikosDataSourceBean oraXaDs = new AtomikosDataSourceBean();
oraXaDs.setXaDataSourceClassName(oraDsProp.getDatasourceClass());
oraXaDs.setUniqueResourceName(oraDsProp.getInstancename());
oraXaDs.setMinPoolSize(oraDsProp.getPoolMinSize());
oraXaDs.setMaxPoolSize(oraDsProp.getPoolMaxSize());
oraXaDs.setTestQuery(oraDsProp.getValidConnectionsql());
Properties oraXaDsProps = oraXaDs.getXaProperties();
oraXaDsProps.setProperty("user",oraDsProp.getUser());
oraXaDsProps.setProperty("password",oraDsProp.getpassword());
oraXaDsProps.setProperty("URL",oraDsProp.getUrl());