用java怎么快速从系统报表页面导出20w条数据

本篇内容介绍了“用java怎么快速从系统报表页面导出20w条数据”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

我们拥有十余年网页设计和网站建设经验,从网站策划到网站制作,我们的网页设计师为您提供的解决方案。为企业提供网站设计、做网站、微信开发、微信小程序开发成都手机网站制作成都h5网站建设、等业务。无论您有什么样的网站设计或者设计方案要求,我们都将富于创造性的提供专业设计服务并满足您的需求。

先不谈技术,先看效果,(完整案例代码文末提供)

数据库为MySQL(理论上此套方案支持任何结构化数据库),准备一张测试表t_person。表结构如下:

CREATE TABLE `t_person` (
  `id` bigint(20) NOT NULL auto_increment,
  `name` varchar(20) default NULL,
  `age` int(11) default NULL,
  `address` varchar(50) default NULL,
  `mobile` varchar(20) default NULL,
  `email` varchar(50) default NULL,
  `company` varchar(50) default NULL,
  `title` varchar(50) default NULL,
  `create_time` datetime default NULL,
  PRIMARY KEY  (`id`)
);

一共9个字段。我们先创建测试数据。

案例代码提供了一个简单的页面,点以下按钮一次性可以创建5w条测试数据:

用java怎么快速从系统报表页面导出20w条数据

这里我连续点了4下,很快就生成了20w条数据,这里为了展示下数据的大致样子,我直接跳转到了最后一页

用java怎么快速从系统报表页面导出20w条数据

然后点开下载大容量文件,点击执行执行按钮,开始下载t_person这张表里的全部数据

用java怎么快速从系统报表页面导出20w条数据

点击执行按钮之后,点下方刷新按钮,可以看到一条异步下载记录,状态是P,表示pending状态,不停刷新刷新按钮,大概几秒后,这一条记录就变成S状态了,表示Success

用java怎么快速从系统报表页面导出20w条数据

然后你就可以下载到本地,文件大小大概31M左右

用java怎么快速从系统报表页面导出20w条数据

看到这里,很多童鞋要疑惑了,这下载下来是csv?csv其实是文本文件,用excel打开会丢失格式和精度。这解决不了问题啊,我们要excel格式啊!!

其实稍微会一点excel技巧的童鞋,可以利用excel导入数据这个功能,数据->导入数据,根据提示一步步,当中只要选择逗号分隔就可以了,关键列可以定义格式,10秒就能完成数据的导入

用java怎么快速从系统报表页面导出20w条数据

你只要告诉运营小姐姐,根据这个步骤来完成excel的导入就可以了。而且下载过的文件,还可以反复下。

是不是从本质上解决了下载大容量数据集的问题?

原理和核心代码

学弟听到这里,很兴奋的说,这套方案能解决我这里的痛点。快和我说说原理。

其实这套方案核心很简单,只源于一个知识点,活用JdbcTemplate的这个接口:

@Override
public void query(String sql, @Nullable Object[] args, RowCallbackHandler rch) throws DataAccessException {
  query(sql, newArgPreparedStatementSetter(args), rch);
}

sql就是select * from t_personRowCallbackHandler这个回调接口是指每一条数据遍历后要执行的回调函数。现在贴出我自己的RowCallbackHandler的实现

private class CsvRowCallbackHandler implements RowCallbackHandler{

    private PrintWriter pw;

    public CsvRowCallbackHandler(PrintWriter pw){
        this.pw = pw;
    }

    public void processRow(ResultSet rs) throws SQLException {
        if (rs.isFirst()){
            rs.setFetchSize(500);
            for (int i = 0; i < rs.getMetaData().getColumnCount(); i++){
                if (i == rs.getMetaData().getColumnCount() - 1){
                    this.writeToFile(pw, rs.getMetaData().getColumnName(i+1), true);
                }else{
                    this.writeToFile(pw, rs.getMetaData().getColumnName(i+1), false);
                }
            }
        }else{
            for (int i = 0; i < rs.getMetaData().getColumnCount(); i++){
                if (i == rs.getMetaData().getColumnCount() - 1){
                    this.writeToFile(pw, rs.getObject(i+1), true);
                }else{
                    this.writeToFile(pw, rs.getObject(i+1), false);
                }
            }
        }
        pw.println();
    }

    private void writeToFile(PrintWriter pw, Object valueObj, boolean isLineEnd){
        ...
    }
}

这个CsvRowCallbackHandler做的事就是每次从数据库取出500条,然后写入服务器上的本地文件中,这样,无论你这条sql查出来是20w条还是100w条,内存理论上只占用500条数据的存储空间。等文件写完了,我们要做的,只是从服务器把这个生成好的文件download到本地就可以了。

因为内存中不断刷新的只有500条数据的容量,所以,即便多线程下载的环境下。内存也不会因此而溢出。这样,完美解决了多人下载的场景。

当然,太多并行下载虽然不会对内存造成溢出,但是会大量占用IO资源。为此,我们还是要控制下多线程并行的数量,可以用线程池来提交作业

ExecutorService threadPool = Executors.newFixedThreadPool(5);

threadPool.submit(new Thread(){
	@Override
	public void run() {
    下载大数据集代码
  }
}

最后测试了下50w这样子的person数据的下载,大概耗时9秒,100w的person数据,耗时19秒。这样子的下载效率,应该可以满足大部分公司的报表导出需求吧。

“用java怎么快速从系统报表页面导出20w条数据”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!


新闻标题:用java怎么快速从系统报表页面导出20w条数据
本文网址:http://pwwzsj.com/article/jichid.html