在运行中将数据流式传输到速度模板

时间:2012-08-27 13:38:21

标签: java velocity

有人可以告诉我,是否有可能以某种方式打开Velocity Excel模板并在运行时流式传输部分更大量的数据?

假设我想在外部资源ArrayLists的循环中读取数据。一个列表,每次迭代有10 000个项目。在简单的迭代中,我想将列表推送到Velocity Excel模板,并通过跳转到下一次迭代而忘记它。在数据处理结束时,我会将Velocity上下文和模板与所有数据进行最终合并。

到目前为止,我已经看到了通过Velocity引擎生成Excel报告的几种简单步骤:

  • 创建Velocity模板
  • 创建Velocity上下文
  • 将数据放入上下文
  • 合并上下文和模板

但我需要多次重复第3步。

2 个答案:

答案 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()调用中的项目。