> 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());