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。
步骤说明
- 在Spring中编写数据查询逻辑,获取每个数据集的列表
- 将每个列表包装为
JRBeanCollectionDataSource,放入参数Map - 在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
相关产品推荐
相关产品推荐

