首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

FineReport 程序數據集開發指南:實現動態表名查詢與報表綁定

     編輯:Java 相關知識

場景:根據參數動態切換數據源

實際報表開發中,常需根據傳入參數(如表名)動態查詢不同資料表。FineReport 通過繼承 AbstractTableData 抽象類實現「程序數據集」,支援帶參數的動態數據源。

核心步驟與完整代碼

1. 定義參數與表結構

public class ParamTableDataDemo extends AbstractTableData {
    private String[] columnNames = null;
    private int columnNum = 10;          // 最大列數
    private int colNum = 0;              // 實際查詢列數
    private ArrayList valueList = null;  // 數據緩存

    public ParamTableDataDemo() {
        // 定義參數:tableName
        setDefaultParameters(new Parameter[] { new Parameter("tableName") });
        // 初始化列名佔位
        columnNames = new String[columnNum];
        for (int i = 0; i < columnNum; i++) {
            columnNames[i] = "column#" + i;
        }
    }

2. 實現數據初始化 init()

public void init() {
    if (valueList != null) return; // 單例模式,避免重複查詢

    String tableName = parameters[0].getValue().toString();
    String sql = "select * from " + tableName + ";";
    FRContext.getLogger().info("Query SQL: " + sql);

    valueList = new ArrayList();
    Connection conn = getConnection();
    try {
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        ResultSetMetaData rsmd = rs.getMetaData();
        colNum = rsmd.getColumnCount();

        Object[] objArray;
        while (rs.next()) {
            objArray = new Object[colNum];
            for (int i = 0; i < colNum; i++) {
                objArray[i] = rs.getObject(i + 1);
            }
            valueList.add(objArray);
        }
        rs.close(); stmt.close(); conn.close();
        FRContext.getLogger().info("Rows fetched: " + valueList.size());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

3. 實現抽象方法

public int getColumnCount() { return columnNum; }
public String getColumnName(int columnIndex) { return columnNames[columnIndex]; }
public int getRowCount() { init(); return valueList.size(); }
public Object getValueAt(int rowIndex, int columnIndex) {
    init();
    if (columnIndex >= colNum) return null;
    return ((Object[]) valueList.get(rowIndex))[columnIndex];
}

4. 資料庫連接與資源釋放

public Connection getConnection() {
    String driverName = "org.sqlite.JDBC";
    String url = "jdbc:sqlite://D:\\FineReport_8.0\\WebReport\\FRDemo.db";
    // 實際專案請替換為生產數據源(JNDI/連接池)
    try {
        Class.forName(driverName);
        return DriverManager.getConnection(url, "", "");
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

public void release() throws Exception {
    super.release();
    this.valueList = null; // 釋放緩存,支援重複調用
}

部署與配置流程

  1. 編譯打包: 將 ParamTableDataDemo.class 放入報表工程 /WEB-INF/classes/com/fr/data/ 目錄(對應 package)。
  2. 新建程序數據集: 報表設計器 → 數據集 → 新建程序數據集 → 選擇 com.fr.data.ParamTableDataDemo,自定義名稱(如 divtable)。
    新建程序數據集
  3. 預覽測試: 輸入表名參數(如 STSCORE),點擊預覽即可動態獲取數據。
    參數輸入 數據預覽
  4. 報表設計: 像普通數據集一樣拖拽字段綁定單元格,完成模板製作。

關鍵注意點

  • 連接字串: 代碼中 SQLite 僅為演示,生產環境務必改用生產數據源(JNDI/DataSource)。
  • SQL 注入風險: 表名拼接 SQL 需嚴格校驗白名單,防止注入攻擊。
  • 效能優化: 大數據量建議增加分頁邏輯或使用流式處理,避免一次性載入所有行至 ArrayList。
  • 線程安全: valueList 為實例變量,FineReport 會為每次查詢創建新實例,天然線程安全。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved