Мой ThreadPoolTaskExecutor corePoolSize равен 5, и в конфигурации bean-компонента JdbcPaginingItemReader я установил для saveState значение false (для документации это значение должно быть установлено равным false, если используется в многопоточном окружении), и в моей таблице есть первичный ключ, который я использую в Атрибут sortKey в queryProvider, когда исполнитель задач порождает все пять потоков одновременно, все они пытаются прочитать данные, startAfterValues из JdbcPaginingItemReader портится. Вызов читателя из каждого потока считывает дублирующиеся строки из-за того, что startAfterValues не является потокобезопасным.
Как мне преодолеть это?
Вот моя информация о конфигурации.
<job id="myJob" xmlns="http://www.springframework.org/schema/batch" incrementer="jobIncrementer">
<step id="step1">
<tasklet task-executor="myTaskExecutor">
<chunk reader="myReader" writer="myWriter" commit-interval="1000" />
<transaction-attributes isolation="READ_COMMITTED" />
</tasklet>
</step>
</job>
<bean id="myReader" class="org.springframework.batch.item.database.JdbcPagingItemReader" scope="step">
<property name="dataSource" ref="myDataSource" />
<property name="queryProvider">
<bean class="org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="selectClause" value="SELECT ID, NAME"/>
<property name="fromClause" value="FROM EMPLOYEE" />
<property name="whereClause" value="where 1=1" />
<property name="sortKey" value="ID"/>
</bean>
</property>
<property name="pageSize" value="1000"/>
<property name="fetchSize" value="1000"/>
<property name="saveState" value="false"/>
<property name="rowMapper">
<bean class="com...MyRowMapper"/>
</property>
</bean>
<bean id="myWriter" class="com...MyItemWriter" scope="step">
<constructor-arg name="jdbcTemplate" ref="jdbcTemplate" />
<constructor-arg name="namedParamJdbcTemplate" ref="namedParamJdbcTemplate" />
<constructor-arg name="endUserID" value="123" />
</bean>
<bean id="myTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10"/>
</bean>