You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring调用含多数据集查询的Jasper Report生成空报表问题求助

问题诊断

你遇到的空报表问题,核心原因是Spring调用时没有给JasperReport提供执行内置查询的必要条件:Jaspersoft Studio预览时会自动使用你配置的数据库连接执行模板里的查询,但你的代码只传了模板路径和空参数Map,既没传数据库连接,也没传入数据集数据,所以Jasper没法填充任何内容。

两种解决方案

方案1:让Jasper自行执行模板内的查询

如果你想保留模板中定义的数据集查询逻辑,只需要在填充报表时传入数据库连接,Jasper会自动执行所有内置查询并填充数据。

代码修改示例

@Autowired
private DataSource dataSource; // 注入Spring中配置的数据库数据源

@GetMapping("/report")
void generateReport(HttpServletResponse response) throws IOException, JRException {
    String templatePath = new File("C:\\Users\\User\\JaspersoftWorkspace\\MyReports\\base3.jasper").getAbsolutePath();
    Map<String, Object> reportParams = new HashMap<>();
    
    // 若模板有参数(比如查询条件),在此添加:reportParams.put("paramKey", paramValue);
    
    // 通过数据源获取连接,传给Jasper执行查询
    try (Connection dbConn = dataSource.getConnection()) {
        JasperPrint jasperPrint = JasperFillManager.fillReport(templatePath, reportParams, dbConn);
        
        // 导出Excel配置
        JRXlsxExporter exporter = new JRXlsxExporter();
        SimpleXlsxReportConfiguration xlsxConfig = new SimpleXlsxReportConfiguration();
        xlsxConfig.setSheetNames(new String[]{"sheet1"});
        exporter.setConfiguration(xlsxConfig);
        exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
        exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(response.getOutputStream()));
        
        // 设置响应头
        response.setHeader("Content-Disposition", "attachment;filename=testName.xlsx");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        exporter.exportReport();
    }
}

注意事项

  • 确保Spring配置的DataSource和你在Jaspersoft Studio中使用的数据库一致
  • 模板中的查询参数必须通过reportParams传入,Jasper会自动替换SQL中的参数占位符

方案2:Spring查询数据后传给Jasper

如果需要在业务层统一处理数据(比如多数据集的关联、复杂过滤),可以手动查询每个子表的数据,包装成数据源后作为参数传给Jasper。

步骤说明

  1. 在Spring中编写数据查询逻辑,获取每个数据集的列表
  2. 将每个列表包装为JRBeanCollectionDataSource,放入参数Map
  3. 在Jaspersoft Studio中,把对应数据集的数据源改为参数数据源(比如设置数据源表达式为$P{childDataSource1})

代码修改示例

@Autowired
private YourDataService dataService; // 自定义数据查询服务

@GetMapping("/report")
void generateReport(HttpServletResponse response) throws IOException, JRException {
    String templatePath = new File("C:\\Users\\User\\JaspersoftWorkspace\\MyReports\\base3.jasper").getAbsolutePath();
    Map<String, Object> reportParams = new HashMap<>();
    
    // 查询主表数据并传入
    List<MainEntity> mainData = dataService.getMainData();
    reportParams.put("mainDataSource", new JRBeanCollectionDataSource(mainData));
    
    // 查询子表1数据并传入
    List<Child1Entity> child1Data = dataService.getChild1Data();
    reportParams.put("child1DataSource", new JRBeanCollectionDataSource(child1Data));
    
    // 查询子表2数据并传入
    List<Child2Entity> child2Data = dataService.getChild2Data();
    reportParams.put("child2DataSource", new JRBeanCollectionDataSource(child2Data));
    
    // 使用空数据源填充,因为所有数据集都通过参数传入
    JasperPrint jasperPrint = JasperFillManager.fillReport(templatePath, reportParams, new JREmptyDataSource());
    
    // 导出Excel配置(同方案1)
    JRXlsxExporter exporter = new JRXlsxExporter();
    SimpleXlsxReportConfiguration xlsxConfig = new SimpleXlsxReportConfiguration();
    xlsxConfig.setSheetNames(new String[]{"sheet1"});
    exporter.setConfiguration(xlsxConfig);
    exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
    exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(response.getOutputStream()));
    
    response.setHeader("Content-Disposition", "attachment;filename=testName.xlsx");
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    exporter.exportReport();
}

注意事项

  • 实体类的字段名必须和模板中使用的字段名一致(或通过别名映射)
  • 模板中每个数据集的数据源必须对应参数Map中的Key
额外提示

你当前代码里的JRBeanCollectionDataSource sampleDataSource完全没被使用,所以对报表填充没有任何作用,可以直接删除。

内容的提问来源于stack exchange,提问作者Erik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 19:35:25