【问题标题】:Modifying a large set of objects using JPA / EclipseLink使用 JPA / EclipseLink 修改大量对象
【发布时间】:2015-01-28 13:09:33
【问题描述】:

我需要迭代 50k 个对象并更改其中的一些字段。
我的内存有限,所以我不想一次将所有 50k 个对象都放入内存。
我想使用游标使用以下代码来执行此操作,但我想知道我使用游标处理的所有对象是否都留在实体管理器缓存中。
我不想使用偏移量和限制的原因是因为数据库需要更加努力地工作,因为每个页面都是一个完整的新查询。
根据以往的经验,一旦实体管理器缓存变大,更新就会变得非常缓慢。
所以通常我会在每数百次更新后调用 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();

【问题讨论】:

    标签: java jpa eclipselink


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      试试这个示例代码:

          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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-18
        • 2011-07-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多