實現多資料來源混合計算的效能最佳化方案之一

xiaohuihui發表於2019-12-27

報表資料經常來自於多個資料來源,如不同的資料庫、檔案、分散式檔案系統等。傳統報表工具往往要藉助第三方程式(如 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
    }
]
}

目標報表格式要求:

imagepng

其中,左半部分來源訂單 JSON 檔案;右半部分來源資料庫客戶表;二者透過客戶編號關聯。

自定義資料集實現

1、連線資料來源

在報表設計器中連線資料來源

imagepng

2、設定報表引數

新建報表,並設定報表引數(發貨起止日期)

imagepng

3、設定報表資料集

imagepng

其中 ds1 為自定義資料集,用於解析 JSON 檔案:

imagepng

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、編輯報表表示式

imagepng

這就是透過自定義資料集實現多資料來源混合計算的過程。可以看到,潤乾報表的自定義資料集介面提供了較大的靈活性,使用者可以自由編寫程式碼完成資料來源準備。不過和傳統報表工具藉助第三方程式一樣,編碼較為複雜,因此自定義資料來源的使用難度較大,本例中只解析 JSON 串並過濾,程式碼就已經很長,如果再完成關聯運算將會更加複雜。

而潤乾報表提供的指令碼資料集(結合集算器實現)可以很好解決上述問題,下面來看實現過程。

指令碼資料集實現

1、 報表引數設定

如上

2、設定資料集

在資料集設定視窗選擇“指令碼資料集”,編寫指令碼同時讀取 JSON 格式檔案和資料庫表完成關聯查詢,十分簡單:

imagepng

指令碼配置如下:

A
1 =file(“D:\\orders.json”).read().import@j().(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、編輯報表表示式

根據指令碼資料集返回的結果,編寫如下報表表示式,完成報表製作

imagepng

可以看到,使用指令碼資料集的方法除了程式碼簡單易懂之外,還有個顯著優點:關聯運算在指令碼中完成,執行效率更高。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69900830/viewspace-2671010/,如需轉載,請註明出處,否則將追究法律責任。

相關文章