代码之家  ›  专栏  ›  技术社区  ›  Julian

用于创建JasperReport后未释放池连接

  •  1
  • Julian  · 技术社区  · 7 年前

    我们已经在prod中使用了spring boot 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;
                }
            }
        }
    }
    

    这些报告运行良好,但在生成10个报告后,我们开始从Hitaki数据源收到超时异常,抱怨它无法在30秒内获得连接。

    我们可以看到,连接池中的默认连接大小为AkiTen IN_USE .将数据源更改为commons dbcp并没有太大变化。这次没有超时,但在生成八份报告后,处理被无限期阻止。八是dbcp数据源的默认池大小。

    结论是这不是数据源问题,我们在jasper罐子中放了一些断点,并注意到结果集和创建的准备语句都已正确关闭。

    我们的Hitaki/DBCP数据源由spring TransactionWaredataSourceProxy实例包装。拿出包装纸什么也没变。

    最后,我用一个非常基本的数据源(显然不适合生产)替换了数据源,并且一切正常。请参见下面的代码,其中显示了我们的尝试:

        @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报告的新手,我只希望我没有正确使用它。

    提前谢谢你。

    3 回复  |  直到 7 年前
        1
  •  1
  •   Rand0m    7 年前

    尝试将创建的连接对象传递给fillReport方法。

    connection = dataSource.getConnection();
    final JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, dataSource.getConnection());
    

    connection = dataSource.getConnection();
            final JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, connection);
    

    干杯

        2
  •  1
  •   smaudi    4 年前

    对我来说,试着利用有用的资源:

    JasperPrint jasperPrint;
        try (Connection connection = dataSource.getConnection()) {
          jasperPrint = JasperFillManager.fillReport(report, params, connection);
        }
    
        3
  •  0
  •   Petho Alpár    4 年前

    对我来说,使用DataSourceUtils:

    connection = DataSourceUtils.doGetConnection(dataSource);
    JasperPrint jasperPrint = JasperFillManager.fillReport(report, params, connection);
    

    ...

    DataSourceUtils.releaseConnection(connection, dataSource);
    

    在每次通话后使用简单连接时,我有-1个空闲连接池。