SpringBatch JpaPagingItemReader 排序顺序
SpringBatch JpaPagingItemReader SortOrder
我使用的是 SpringBatch 版本 3.0.7、Hibernate 4.3.11 和 H2 数据库。使用 JpaPagingItemReader 时,JPQL 是否需要唯一的排序顺序?我发现 JdbcPagingItemReader 需要它(请参阅 BATCH-2465)。
在一个步骤中,我使用 JpaPagingItemReader 从数据库加载实体,然后将它们写入平面文件。我希望平面文件包含按 JPQL 指定的顺序排序的唯一实体。如果我将页面大小设置为较小的值(例如 1),然后提供一个 JPQL 语句来对具有非唯一键的实体进行排序,我会看到同一实体在输出文件中重复多次。如果我按唯一键排序,则没有 "duplicates"。如果我设置页面大小 >= 实体总数,那么只有 1 页,没有 "duplicates".
根据经验,JpaPagingItemReader 似乎需要 JPQL 具有唯一的排序键。
查看 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
}
如您所见,对于读取的每个页面,都会为每个页面创建一个新查询。因此,必须确保您的查询 returns 始终 相同数量 的元素 完全 相同的顺序,因此,它需要 'unique sort key'。否则您将有重复项和缺失项(每个重复项都会有一个缺失项,因为总行数将相同)。
我使用的是 SpringBatch 版本 3.0.7、Hibernate 4.3.11 和 H2 数据库。使用 JpaPagingItemReader 时,JPQL 是否需要唯一的排序顺序?我发现 JdbcPagingItemReader 需要它(请参阅 BATCH-2465)。
在一个步骤中,我使用 JpaPagingItemReader 从数据库加载实体,然后将它们写入平面文件。我希望平面文件包含按 JPQL 指定的顺序排序的唯一实体。如果我将页面大小设置为较小的值(例如 1),然后提供一个 JPQL 语句来对具有非唯一键的实体进行排序,我会看到同一实体在输出文件中重复多次。如果我按唯一键排序,则没有 "duplicates"。如果我设置页面大小 >= 实体总数,那么只有 1 页,没有 "duplicates".
根据经验,JpaPagingItemReader 似乎需要 JPQL 具有唯一的排序键。
查看 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
}
如您所见,对于读取的每个页面,都会为每个页面创建一个新查询。因此,必须确保您的查询 returns 始终 相同数量 的元素 完全 相同的顺序,因此,它需要 'unique sort key'。否则您将有重复项和缺失项(每个重复项都会有一个缺失项,因为总行数将相同)。