Hibernate:走数百万行并且不会泄漏内存

Jef*_*and 6 java performance orm hibernate batch-file

下面的代码功能,但Hibernate永远不会放任何对象.调用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Jef*_*and 0

我认为我的问题之一是

if (sr.isLast()) {
    advanceScroll();
    //...
Run Code Online (Sandbox Code Playgroud)

结合

((Session) Main.em.getDelegate()).clear();
//Also, "Main.em.clear()" should do...
Run Code Online (Sandbox Code Playgroud)

导致过早地刷新数据库一次运行。这就是集合异常的原因。集合不能在 StatelessSession 中处理,因此这是不可能的。我不知道为什么在工作session.evict(currentObject)时无法工作Session.clear(),但这就是我现在必须处理的方式。我会把答案扔给任何能找出答案的人。

所以,现在我们有了答案。需要手动滚动窗口,关闭 ScrollableResults 没有帮助,我需要正确运行 Session.clear()。