实现多数据源混合计算的方案之一
报表数据经常来自于多个数据源,如不同的数据库、文件、分布式文件系统等。传统报表工具往往要借助第三方程序(如 JAVA 自定义数据源)完成多数据源的访问,过程复杂、代码难写,而且会导致应用系统与报表系统耦合度过高,从而增加后期维护难度。而润乾报表除了支持自定义数据源外,还可以用脚本数据集直接进行多数据源的混合计算。下面通过实际例子分别来看一下这两种方法。
这里以查询某发货时间段内所有订单的客户信息为例,业务系统中,订单信息存储于 JSON 格式的文件,报表查询时需要读取 JSON 格式文件,并与数据库表(维表)进行联合查询。
orders.json 部分内容如下:
{ "orders":[ { "订单ID": "10248", "订单编号": [ { "订单ID": "10248", "产品ID": "5", "单价": 12, "折扣": 0, "数量": 1 } ], "客户ID": "VINET", "发货日期": "2000-07-16", "到货日期": "1996-08-01", "运货费": 32.38 }, …… { "订单ID": "10400", "客户ID": "EASTC", "发货日期": "1997-01-16", "到货日期": "1997-01-29", "运货费": 83.93 } ] }
目标报表格式要求:
其中,左半部分来源订单 JSON 文件;右半部分来源数据库客户表;二者通过客户编号关联。
自定义数据集实现
1、连接数据源
在报表设计器中连接数据源
2、设置报表参数
新建报表,并设置报表参数(发货起止日期)
3、设置报表数据集
其中 ds1 为自定义数据集,用于解析 JSON 文件:
ds2 为 SQL 数据集,读取数据库客户表信息:
SELECT * FROM 客户
JSONDataSet.java 内容如下:
public class JSONDataSet implements IDataSetFactory { public DataSet createDataSet(Context ctx, DataSetConfig dsc, boolean retrieve) { // 取得参数列表并分别取得它的参数名与值,宏与之类似 Map map = ctx.getParamMap(false); String begin = null; String end = null; if (map != null) { begin = map.get("begin").toString(); end = map.get("end").toString(); } DataSet ds1 = new DataSet("ds1"); String[] filds = { "订单ID", "发货日期", "客户ID" }; for (int i = 0; i < filds.length; i++) { ds1.addCol(filds[i]);// 设置数据集的字段 } String JsonContext = new JSONDataSet().ReadFile("D:\\orders.json"); try { JSONObject jo = new JSONObject(JsonContext); JSONArray ja = jo.getJSONArray("orders"); for (int i = 0; i < ja.length(); i++) { String tdate = ja.getJSONObject(i).getString("发货日期"); if (tdate.compareTo(begin) >= 0 && end.compareTo(tdate) >= 0) { Row rr = ds1.addRow(); String id = ja.getJSONObject(i).getString("订单ID"); String cusid = ja.getJSONObject(i).getString("客户ID"); rr.setData(1, id); rr.setData(2, tdate); rr.setData(3, cusid); } } } catch (Exception e) { e.printStackTrace(); } return ds1; } public String ReadFile(String Path) { BufferedReader reader = null; String laststr = ""; try { FileInputStream fileInputStream = new FileInputStream(Path); InputStreamReader inputStreamReader = new InputStreamReader( fileInputStream, "GBK"); reader = new BufferedReader(inputStreamReader); String tempString = null; while ((tempString = reader.readLine()) != null) { laststr += tempString; } reader.close(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return laststr; } }
注意,这里使用了 json_org.jar 解析 JSON 串,使用时需要引入。
4、编辑报表表达式
这就是通过自定义数据集实现多数据源混合计算的过程。可以看到,润乾报表的自定义数据集接口提供了较大的灵活性,用户可以自由编写代码完成数据源准备。不过和传统报表工具借助第三方程序一样,编码较为复杂,因此自定义数据源的使用难度较大,本例中只解析 JSON 串并过滤,代码就已经很长,如果再完成关联运算将会更加复杂。
而润乾报表提供的脚本数据集(结合集算器实现)可以很好解决上述问题,下面来看实现过程。
脚本数据集实现
1、报表参数设置
如上
2、设置数据集
在数据集设置窗口选择“脚本数据集”,编写脚本同时读取 JSON 格式文件和数据库表完成关联查询,十分简单:
脚本配置如下:
A | |
---|---|
1 | =file(“D:\\orders.json”).read()[email protected]().(orders) |
2 | =A1.select(发货日期 >=begin && 发货日期 <=end) |
3 | =demo.query(“select * from 客户”) |
4 | =A3.switch(客户 ID; 客户 ID:A3) |
5 | =A4.new(订单 ID, 发货日期, 客户 ID. 客户 ID: 客户编号, 客户 ID. 公司名称: 公司名称, 客户 ID. 联系人姓名: 姓名, 客户 ID. 电话: 电话, 客户 ID. 地址: 地址) |
6 | result A5 |
代码说明:
A1:通过指定选项 @j 通过 import 函数读取订单信息 JSON 格式文件
A2:根据发货日期范围过滤数据
A3:查询数据库客户表信息
A4:根据客户 ID 关联文件和数据表,完成混合计算
A5:根据关联结果新建结果集,并返回给报表
3、编辑报表表达式
根据脚本数据集返回的结果,编写如下报表表达式,完成报表制作
可以看到,使用脚本数据集的方法除了代码简单易懂之外,还有个显著优点:关联运算在脚本中完成,执行效率更高。