这个Hibernate分页机制有什么问题?

时间:2016-11-03 07:50:30

标签: java hibernate

我根据表中的行数制作了一个动态批处理选择器,以避免内存泄漏。但是,这段代码似乎无法检索数据库中的最后几千行

基本上,代码如下所示:

{{1}}

为了澄清,cacheDetail.getQuery()只是一个HQL select语句:“FROM tableX”。

那么代码中的哪个地方我错了?

2 个答案:

答案 0 :(得分:1)

您没有将结果合并到单个列表(total),因为您只获取最后一个结果,您可以查看下面的精炼代码:

Session session = HibernateUtil.getSessionFactory().openSession();

int i = 0;
int batch = 5000; //process in batches if table is too big
Long rowCount = (Long) session.createQuery("select count(*) " + cacheDetail.getQuery()).list().get(0);

//Create a new list to sum each batch    
List<Object> total = new ArrayList<>();

System.out.println("Starting execution on " + cacheDetail.getQuery());
if (rowCount > batch) {
    List<Object> list = session.createQuery(cacheDetail.getQuery())
            .setFirstResult(i).setMaxResults(batch).list();
    total.addAll(list);

    while(list.size() == batch || list.size() < batch) {
        i+=batch;

        if (list.size() < batch) {
        list = session.createQuery(cacheDetail.getQuery())
                .setFirstResult(i).setMaxResults(list.size()).list();
        } else {
        list = session.createQuery(cacheDetail.getQuery())
                .setFirstResult(i).setMaxResults(batch).list(); 
        }

        total.addAll(list);//add to total
        //Do some computation, close session
    }
} else { //what if row count is less than batch, YOU DID NOT HANDLE
    List<Object> list = session.createQuery(cacheDetail.getQuery())
            .setFirstResult(i).setMaxResults(rowCount).list();
            total.addAll(list);
       //Do some computation, close session
}

答案 1 :(得分:0)

感谢输入javaguy和ST-DDT。为了回应您的评论,我将hibernate对象加载到内存分布式映射中。我将您的解决方案组合在一起并将其定制为类似的东西(使用rowCount本身,这不应该使其容易进行数据库修改)。似乎它工作正常,也希望你的输入:

int i = 0;
int batch = 5000; //process in batches if table is too big

Long rowCount = (Long) session.createQuery("select count(*) " + cacheDetail.getQuery()).list().get(0);

System.out.println("Starting execution on " + cacheDetail.getQuery());
if (rowCount > batch) { //do batch processing
    List<Object> list = session.createQuery(cacheDetail.getQuery())
            .setFirstResult(i).setMaxResults(batch).list();
    //Load objects from list to a map   

    while(list.size() == batch){
        i += batch;
        rowCount -= batch;
        list = session.createQuery(cacheDetail.getQuery())
                .setFirstResult(i).setMaxResults(batch).list();
    //Load objects from list to a map

    }
    if (rowCount < batch){
        System.out.println("Loading the last " + rowCount + " records.");
        list = session.createQuery(cacheDetail.getQuery())
                .setFirstResult(i).setMaxResults((int)(long)rowCount).list(); 
   //load objects from list to map
    }

    list = null;
    session.flush();
    session.clear();
}
 //Else, use a non paging mechanism to select from DB (trivial)

虽然我真的不热衷于使用你发布的Total列表,因为我不想要重复,而是宁愿像ST-DDT那样处理它。