Будьте в спящем режиме: Обход миллионы строк и не пропускает память

Ниже функций кода, но В спящем режиме, никогда не отпускает его власти никакого объекта. Вызов session.clear() исключения причин относительно выборки класса, к которому присоединяются и вызова session.evict(currentObject) прежде, чем получить следующий объект также не удается освободить память. В конечном счете я исчерпываю свое пространство "кучи".

Проверяя мои дампы "кучи", StatefulPersistenceContext является сборщиком "мусора", поддерживают все ссылки, указывающие на мои объекты.

public class CriteriaReportSource implements JRDataSource {

    private ScrollableResults sr;
    private Object currentObject;
    private Criteria c;
    private static final int scrollSize = 10;
    private int offset = 1;

    public CriteriaReportSource(Criteria c) {
        this.c = c;
        advanceScroll();
    }

    private void advanceScroll() {
//        ((Session) Main.em.getDelegate()).clear();
        this.sr = c.setFirstResult(offset)
                   .setMaxResults(scrollSize)
                   .scroll(ScrollMode.FORWARD_ONLY);
        offset += scrollSize;
    }

    public boolean next() {
        if (sr.next()) {
            currentObject = sr.get(0);
            if (sr.isLast()) {
                advanceScroll();
            }
            return true;
        }

        return false;
    }

    public Object getFieldValue(JRField jrf) throws JRException {
        Object retVal = null;
        if(currentObject == null) { return null; }
        try {
            retVal = PropertyUtils.getProperty(currentObject, jrf.getName());
        } catch (Exception ex) {
            Logger.getLogger(CriteriaReportSource.class.getName()).log(Level.SEVERE, null, ex);
        }
        return retVal;
    }
}
6
задан Pascal Thivent 26 June 2010 в 00:11
поделиться

3 ответа

Я думаю, что одна из моих проблем заключалась в том, что

if (sr.isLast()) {
    advanceScroll();
    //...

в сочетании с

((Session) Main.em.getDelegate()).clear();
//Also, "Main.em.clear()" should do...

приводила к тому, что база данных очищалась на один прогон слишком рано. Это было причиной исключений, связанных с коллекциями. Коллекции не могут быть обработаны в StatelessSession, так что это исключено. Я не знаю, почему session.evict(currentObject) не срабатывает, когда Session.clear() работает, но пока мне придется действовать именно так. Я поставлю очки за ответ тому, кто разберется с этим.

Итак, на данный момент у нас есть ответ. Требуется ручная прокрутка окна, закрытие ScrollableResults не помогает, и мне нужно правильно выполнить Session.clear().

0
ответ дан 17 December 2019 в 07:00
поделиться

Не используйте здесь stateful session, это просто НЕ подходящий инструмент для просмотра миллионов строк и построения отчета. Вместо этого используйте интерфейс StatelessSession.

Если использования MySQL Connector/J даже этого недостаточно, вам нужно также победить внутреннюю буферизацию, выполняемую драйвером JDBC, с помощью этого:

Query query = session.createQuery(query);
query.setReadOnly(true);
// MIN_VALUE gives hint to JDBC driver to stream results
query.setFetchSize(Integer.MIN_VALUE);
ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY);
// iterate over results
while (results.next()) {
    Object row = results.get();
    // process row then release reference
    // you may need to evict() as well
}
results.close();
4
ответ дан 17 December 2019 в 07:00
поделиться

Я бы предложил пару вещей:

Попробуйте вызвать setCacheMode (CacheMode.IGNORE) в Criteria, прежде чем открывать его.

В методе advanceScroll () добавьте if (sr! = Null) sr.close (); , чтобы предыдущие результаты ScrollableResults закрылись перед повторным назначением. к новому.

Один вопрос: в чем причина вызова setMaxSize (), отслеживания смещения и повторного открытия прокручиваемых результатов, почему бы просто не сделать это?

public CriteriaReportSource(Criteria c) {
    this.c = c;
    this.sr = c.setCacheMode(CacheMode.IGNORE)
               .scroll(ScrollMode.FORWARD_ONLY);
}


public boolean next() {
    if (sr.next()) {
        currentObject = sr.get(0);
        return true;
    }
    return false;
}
0
ответ дан 17 December 2019 в 07:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: