池连接在用于创建 JasperReport 后未被释放
pooled connection not being freed after used to create JasperReport
我们有一个已经在产品中使用的 spring 引导 Web 应用程序。
最近,该企业要求以不可编辑的 PDF 格式生成一些 EOD 核对报告。
我们编译了一些 Jasper 报告并开始使用如下代码生成报告:
private void generatePdfReport(final Report report) throws SQLException, JRException {
final JasperReport jasperReport = JASPER_REPORT_MAP.get(report);
if (jasperReport == null) {
throw new UnsupportedOperationException("The report is not supported: " + report.getName());
} else {
Connection connection = null;
try {
connection = dataSource.getConnection();
final JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, dataSource.getConnection());
final JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(report.getFormattedFilename() + Report.EXT_PDF));
exporter.setConfiguration(reportConfig);
exporter.setConfiguration(exportConfig);
exporter.exportReport();
log.info("PDF Report ({}) exported successfully!", report.getName());
} finally {
if (connection != null) {
log.info("about to close db connection");
connection.close();
connection = null;
}
}
}
}
报告 运行 很好,但在生成十份报告后,我们开始收到来自 Hitaki 数据源的超时异常,抱怨它无法在不到 30 秒的时间内获得连接。
Hitaki 数据源的默认连接池大小为 10,在 Hitaki 中放置一些断点 类 我们可以看到所有 10 个连接都标记为 IN_USE
。将数据源更改为 commons-dbcp 并没有太大变化。这次没有超时,但处理在生成八份报告后无限期地阻塞。八是 dbcp 数据源的默认池大小。
断定这不是数据源问题,我们在 jasper jar 中放置了一些断点,并注意到创建的结果集和准备好的语句都已正确关闭。
我们的 Hitaki/DBCP 数据源由 spring TransactionAwareDataSourceProxy 实例包装。把那层包装纸拿掉什么都没有改变。
最后我用一个非常基本的数据源(显然不适合生产)替换了数据源并且一切正常。请参阅下面的代码,其中显示了我们尝试过的注释:
@Bean
public DataSource dataSource() {
final String url = env.getProperty("database.url");
final String userName = env.getProperty("gmm.schema");
log.info("Creating DataSource for {}@{}", userName, url);
// final HikariDataSource dataSource = new HikariDataSource();
// final BasicDataSource dataSource = new BasicDataSource();
final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(env.getProperty("gmm.password"));
// dataSource.setDriverClassName(env.getProperty("database.driver"));
dataSource.setDriverClass(oracle.jdbc.driver.OracleDriver.class);
return dataSource;
// return new TransactionAwareDataSourceProxy(dataSource);
}
现在我的问题是:
什么会导致这种行为,我应该如何解决或进一步调查。如果我们注释掉报告作业,则没有连接问题,但另一方面,我看不出如何使用非常基本的数据源来解决这个问题。
作为 Jasper Reports 的新手,我只是希望我没有正确使用它。
提前谢谢你。
尝试将您创建的连接对象传递给 fillReport 方法。
connection = dataSource.getConnection();
final JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, dataSource.getConnection());
到
connection = dataSource.getConnection();
final JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, connection);
干杯
我使用 DataSourceUtils:
connection = DataSourceUtils.doGetConnection(dataSource);
JasperPrint jasperPrint = JasperFillManager.fillReport(report, params, connection);
...
DataSourceUtils.releaseConnection(connection, dataSource);
在每次调用后使用简单连接,我有 -1 个空闲连接池。
对我来说,try-with-resources 有效:
JasperPrint jasperPrint;
try (Connection connection = dataSource.getConnection()) {
jasperPrint = JasperFillManager.fillReport(report, params, connection);
}
我们有一个已经在产品中使用的 spring 引导 Web 应用程序。 最近,该企业要求以不可编辑的 PDF 格式生成一些 EOD 核对报告。
我们编译了一些 Jasper 报告并开始使用如下代码生成报告:
private void generatePdfReport(final Report report) throws SQLException, JRException {
final JasperReport jasperReport = JASPER_REPORT_MAP.get(report);
if (jasperReport == null) {
throw new UnsupportedOperationException("The report is not supported: " + report.getName());
} else {
Connection connection = null;
try {
connection = dataSource.getConnection();
final JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, dataSource.getConnection());
final JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(report.getFormattedFilename() + Report.EXT_PDF));
exporter.setConfiguration(reportConfig);
exporter.setConfiguration(exportConfig);
exporter.exportReport();
log.info("PDF Report ({}) exported successfully!", report.getName());
} finally {
if (connection != null) {
log.info("about to close db connection");
connection.close();
connection = null;
}
}
}
}
报告 运行 很好,但在生成十份报告后,我们开始收到来自 Hitaki 数据源的超时异常,抱怨它无法在不到 30 秒的时间内获得连接。
Hitaki 数据源的默认连接池大小为 10,在 Hitaki 中放置一些断点 类 我们可以看到所有 10 个连接都标记为 IN_USE
。将数据源更改为 commons-dbcp 并没有太大变化。这次没有超时,但处理在生成八份报告后无限期地阻塞。八是 dbcp 数据源的默认池大小。
断定这不是数据源问题,我们在 jasper jar 中放置了一些断点,并注意到创建的结果集和准备好的语句都已正确关闭。
我们的 Hitaki/DBCP 数据源由 spring TransactionAwareDataSourceProxy 实例包装。把那层包装纸拿掉什么都没有改变。
最后我用一个非常基本的数据源(显然不适合生产)替换了数据源并且一切正常。请参阅下面的代码,其中显示了我们尝试过的注释:
@Bean
public DataSource dataSource() {
final String url = env.getProperty("database.url");
final String userName = env.getProperty("gmm.schema");
log.info("Creating DataSource for {}@{}", userName, url);
// final HikariDataSource dataSource = new HikariDataSource();
// final BasicDataSource dataSource = new BasicDataSource();
final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(env.getProperty("gmm.password"));
// dataSource.setDriverClassName(env.getProperty("database.driver"));
dataSource.setDriverClass(oracle.jdbc.driver.OracleDriver.class);
return dataSource;
// return new TransactionAwareDataSourceProxy(dataSource);
}
现在我的问题是:
什么会导致这种行为,我应该如何解决或进一步调查。如果我们注释掉报告作业,则没有连接问题,但另一方面,我看不出如何使用非常基本的数据源来解决这个问题。
作为 Jasper Reports 的新手,我只是希望我没有正确使用它。
提前谢谢你。
尝试将您创建的连接对象传递给 fillReport 方法。
connection = dataSource.getConnection();
final JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, dataSource.getConnection());
到
connection = dataSource.getConnection();
final JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, connection);
干杯
我使用 DataSourceUtils:
connection = DataSourceUtils.doGetConnection(dataSource);
JasperPrint jasperPrint = JasperFillManager.fillReport(report, params, connection);
...
DataSourceUtils.releaseConnection(connection, dataSource);
在每次调用后使用简单连接,我有 -1 个空闲连接池。
对我来说,try-with-resources 有效:
JasperPrint jasperPrint;
try (Connection connection = dataSource.getConnection()) {
jasperPrint = JasperFillManager.fillReport(report, params, connection);
}