我使用的是SpringBatch 3.0.7版,Hibernate 4.3.11和H2数据库。使用JpaPagingItemReader时,JPQL是否需要唯一的排序顺序?我发现它是JdbcPagingItemReader所必需的(参见BATCH-2465)。
在一个步骤中,我使用JpaPagingItemReader从数据库加载实体,然后将它们写入平面文件。我希望平面文件包含按JPQL指定的顺序排序的唯一实体。如果我将页面大小设置为小的,如1,然后提供一个JPQL语句,用非唯一键对实体进行排序,我看到同一个实体在输出文件中重复多次。如果我按唯一键排序,则没有“重复”。如果我设置页面大小> =实体总数,那么只有1页,没有“重复”。
根据经验,JpaPagingItemReader似乎要求JPQL具有唯一的排序键。
答案 0 :(得分:1)
看一下JpaPagingItemReader的实现,你会发现方法doReadPage():
@Override
@SuppressWarnings("unchecked")
protected void doReadPage() {
EntityTransaction tx = null;
if (transacted) {
tx = entityManager.getTransaction();
tx.begin();
entityManager.flush();
entityManager.clear();
}//end if
Query query = createQuery().setFirstResult(getPage() * getPageSize()).setMaxResults(getPageSize());
if (parameterValues != null) {
for (Map.Entry<String, Object> me : parameterValues.entrySet()) {
query.setParameter(me.getKey(), me.getValue());
}
}
if (results == null) {
results = new CopyOnWriteArrayList<T>();
}
else {
results.clear();
}
if (!transacted) {
List<T> queryResult = query.getResultList();
for (T entity : queryResult) {
entityManager.detach(entity);
results.add(entity);
}//end if
} else {
results.addAll(query.getResultList());
tx.commit();
}//end if
}
如您所见,对于每个读取的页面,都会为每个页面创建一个新查询。因此,必须确保您的查询始终返回完全相同顺序中相同数量的元素,因此,它需要一个&#39;唯一排序键&# 39 ;.否则,您将有重复项和缺少的条目(每个副本都会有一个缺少的条目,因为总行数将相同)。