3

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

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

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

  • 创建速度模板
  • 创建速度上下文
  • 将数据置于上下文中
  • 合并上下文和模板

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

4

2 回答 2

4

这是我经过测试的解决方案,在我的情况下效果很好。我能够在 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
}
于 2012-09-10T08:15:56.827 回答
2

我看到的默认 Velocity 的唯一选择是实现类似“流式集合”的东西,它永远不会将完整的数据保存在内存中,而是一个一个地提供迭代器中的数据。

然后,您可以将此 Collection 放入 Velocity 上下文中,并在 Velocity 模板中使用它来迭代项目。在内部,Collection 将从您的外部源一个接一个地检索 hasNext()/next() 调用中的项目。

于 2012-08-27T21:25:47.750 回答