我根据表中的行数制作了一个动态批处理选择器,以避免内存泄漏。但是,这段代码似乎无法检索数据库中的最后几千行。
基本上,代码如下所示:
{{1}}
为了澄清,cacheDetail.getQuery()只是一个HQL select语句:“FROM tableX”。
那么代码中的哪个地方我错了?
答案 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那样处理它。