使用 JPA/EclipseLink 修改大量对象

Modifying a large set of objects using JPA / EclipseLink

我需要迭代 50k 个对象并更改其中的一些字段。
我的内存有限,所以我不想一次将所有 50k 对象都放入内存中。
我想用以下代码使用游标来完成它,但我想知道我使用游标处理的所有对象是否都留在实体管理器缓存中。
我不想用 offset 和 limit 来做的原因是因为每个页面都是一个完整的新查询,所以数据库需要更加努力地工作。
从以前的经验来看,一旦实体管理器缓存变大,更新就会变得非常慢。
所以通常我会在每几百次更新后调用 flush 和 clear。
这里的问题是刷新/清除会破坏光标。
我很乐意学习更新大量对象而不将它们全部加载到内存中的最佳方法。
有关 EclipseLink 游标如何在此类场景中工作的其他信息也很有价值。

JpaQuery<T> jQuery = (JpaQuery<T>) query;
jQuery.setHint(QueryHints.RESULT_SET_TYPE, ResultSetType.ForwardOnly)
              .setHint(QueryHints.SCROLLABLE_CURSOR, true);
Cursor cursor = jQuery.getResultCursor();
Iterator<MyObj> cursorIterator = cursor.iterator();
while (cursorIterator.hasNext()) {
      MyObj myObj = cursorIterator.next();
      ChangeMyObj(myObj);
}
cursor.close();

在每页后使用 pagination + entityManager.clear()。还可以在单​​个事务中执行每个页面,或者在发生异常后您必须 create/get 一个新的 EntityManager(至少对于 Hibernate:EntityManager 实例在异常发生后可能处于不一致状态)。

试试这个示例代码:

    List results;
    int index= 0;
    int max = 100;
    do {
    Query query= manager.createQuery("JPQL QUERY");
query.setMaxResults(max).
setFirstResult(index);
 results = query.getResultList( );
    Iterator it = results.iterator( );
    while (it.hasNext( )) {
    Object c = (Object)it.next( );

    }
entityManager.clear( );
index = index + results.getSize( );
} while (results.size( ) > 0);