有人可以告诉我,是否有可能以某种方式打开Velocity Excel模板并在运行时流式传输部分更大量的数据?
假设我想在外部资源ArrayLists的循环中读取数据。一个列表,每次迭代有10 000个项目。在简单的迭代中,我想将列表推送到Velocity Excel模板,并通过跳转到下一次迭代而忘记它。在数据处理结束时,我会将Velocity上下文和模板与所有数据进行最终合并。
到目前为止,我已经看到了通过Velocity引擎生成Excel报告的几种简单步骤:
但我需要多次重复第3步。
答案 0 :(得分:2)
这是我测试过的解决方案,在我的案例中效果很好。我能够生成Excel表格,直接从数据库中加载大量数据。
Connection conn = getDs().getConnection();
// such a configuration of prepared statement is mandatory for large amount of data
PreparedStatement ps = conn.prepareStatement(MY_QUERY, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);
// load huge amount of data per 50000 items
ps.setFetchSize(50000);
ResultSet rs = ps.executeQuery();
// calculate count of returned data earlier
final CountWrapper countWrapper = new CountWrapper(countCalculatedEarlier);
CustomResultSetIterator<MyObject> rowsIter = new CustomResultSetIterator<MyObject>(rs, new org.apache.commons.dbutils.BasicRowProcessor(), MyObject.class) {
private Long iterCount = 0L;
@Override
public boolean hasNext() {
// you can't call isLast method on defined as forward only cursor of result set, hence there is a homegrown calculation whether last item is reached or not
return iterCount < countWrapper.getCount().longValue();
};
@Override
public MyObject next() {
iterCount++;
return super.next();
};
};
VelocityContext context = new VelocityContext();
// place an interator here instead of collection object
context.put("rows", rowsIter);
Template t = ve.getTemplate(template);
File file = new File(parthToFile);
FileWriter fw = new FileWriter(file);
// generate on the fly in my case 1 000 000 rows in Excel, watch out such an Excel may have 1GB size
t.merge(context, fw);
// The CustomResultSetIterator is a:
public class CustomResultSetIterator<E> implements Iterator<E> {
//...implement all interface's methods
}
答案 1 :(得分:1)
我看到默认Velocity的唯一选择是实现像“流式集合”这样的东西,它永远不会在内存中保存完整的数据,而是逐个地在迭代器中提供数据。
然后,您可以将此Collection放入Velocity上下文中,并在Velocity Template中使用它来迭代项目。在内部,Collection将从外部源一个接一个地检索hasNext()/ next()调用中的项目。