【发布时间】:2014-12-18 01:14:20
【问题描述】:
我正在使用 Spring Batch(3.0.1.RELEASE) / JPA 和 HSQLBD 服务器数据库。 我需要浏览整个表格(使用分页)并更新项目(一个接一个)。所以我使用了一个 jpaPagingItemReader。但是当我运行作业时,我可以看到一些行被跳过,并且跳过的行数等于页面大小。例如,如果我的表有 12 行并且 jpaPagingItemReader.pagesize = 3,则作业将读取:第 1、2、3 行,然后是第 7、8、9 行(所以跳过第 4、5、6 行)...... 你能告诉我我的代码/配置有什么问题吗,或者它可能是 HSQLDB 分页的问题? 以下是我的代码:
[EDIT]:问题出在我的 ItemProcessor 上,它对 POJO 实体进行了修改。由于 JPAPagingItemReader 在每次读取之间进行了刷新,因此更新了实体((这是我想要的)。但似乎游标分页也增加了(从日志中可以看出:行 ID 4、5 和 6 已经跳过)。我该如何处理这个问题?
@Configuration
@EnableBatchProcessing(modular=true)
public class AppBatchConfig {
@Inject
private InfrastructureConfiguration infrastructureConfiguration;
@Inject private JobBuilderFactory jobs;
@Inject private StepBuilderFactory steps;
@Bean public Job job() {
return jobs.get("Myjob1").start(step1()).build();
}
@Bean public Step step1() {
return steps.get("step1")
.<SNUserPerCampaign, SNUserPerCampaign> chunk(0)
.reader(reader()).processor(processor()).build();
}
@Bean(destroyMethod = "")
@JobScope
public ItemStreamReader<SNUserPerCampaign> reader() String trigramme) {
JpaPagingItemReader reader = new JpaPagingItemReader();
reader.setEntityManagerFactory(infrastructureConfiguration.getEntityManagerFactory());
reader.setQueryString("select t from SNUserPerCampaign t where t.isactive=true");
reader.setPageSize(3));
return reader;
}
@Bean @JobScope
public ItemProcessor<SNUserPerCampaign, SNUserPerCampaign> processor() {
return new MyItemProcessor();
}
}
@Configuration
@EnableBatchProcessing
public class StandaloneInfrastructureConfiguration implements InfrastructureConfiguration {
@Inject private EntityManagerFactory emf;
@Override
public EntityManagerFactory getEntityManagerFactory() {
return emf;
}
}
来自我的 ItemProcessor:
@Override
public SNUserPerCampaign process(SNUserPerCampaign item) throws Exception {
//do some stuff …
//then if (condition) update the Entity pojo :
item.setModificationDate(new Timestamp(System.currentTimeMillis());
item.setIsactive = false;
}
来自 Spring xml 配置文件:
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001/MYAppDB" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
跟踪/日志总结:
11:16:05.728 TRACE MyItemProcessor - item processed: snUserInternalId=1]
11:16:06.038 TRACE MyItemProcessor - item processed: snUserInternalId=2]
11:16:06.350 TRACE MyItemProcessor - item processed: snUserInternalId=3]
11:16:06.674 DEBUG SQL- update SNUSER_CAMPAIGN set ...etc...
11:16:06.677 DEBUG SQL- update SNUSER_CAMPAIGN set ...etc...
11:16:06.679 DEBUG SQL- update SNUSER_CAMPAIGN set ...etc...
11:16:06.681 DEBUG SQL- select ...etc... from SNUSER_CAMPAIGN snuserperc0_
11:16:06.687 TRACE MyItemProcessor - item processed: snUserInternalId=7]
11:16:06.998 TRACE MyItemProcessor - item processed: snUserInternalId=8]
11:16:07.314 TRACE MyItemProcessor - item processed: snUserInternalId=9]
【问题讨论】:
-
您如何确认正在读取哪些行?您可以提供任何堆栈跟踪/日志信息吗?
-
我意识到问题是我的 ItemProcessor 改变了实体 pojo,我通过添加跟踪来编辑我的问题
-
我有点困惑。从
JpaPagingItemReader返回的项目是分离的,因此在没有明确写入的情况下不应更新它们。能否提供完整的作业配置? -
我明天会尝试添加更多细节。无论如何,我在 Spring JPAPagingItemreader 的源代码中可以看到,在阅读下一页时,这些项目似乎是分离的(通过对上下文进行刷新和清除)。这就是为什么我不需要 ItemWritter 来持久化我的更新。一个重要的细节可能是,在我的项目处理器中,我更新了我的 SELECT where 子句中的布尔值;不知道这样能不能修改分页光标。
-
冲洗和清除只是一开始的清理。在
JpaPagingItemReader结束时,我们循环遍历元素并显式分离它们,或者提交事务以便分离它们。无论哪种方式,从JpaPagingItemReader返回的实体都应该处于分离状态。您可以发布完整工作的配置吗?
标签: jpa spring-batch