我正在使用itext 7 pdf从jdbc查询生成pdf.它可以处理4000条记录,但一旦我们在表中插入17000条记录,我就开始让Java内存不足.我一次获取所有数据,如下所示,如何修改它以使用分页查询,并将所有分页结果缝合到一个PDF中.

这是我的驱动程序代码,它输入表名和HttpServlet,并将其传递给实现ResultsTextRactor的类.

public void generatePDF(String tableName, HttpServletResponse response, String[] filter) throws DataAccessException, IOException {
        //Table validation logic
        String sql = "select * from table";
        mainJdbcTemplate.query(sql, paramMap,
                new StreamingPDFResultSetExtractor(response.getOutputStream(), tableName));
    }

实现结果集提取器的自定义类.我输入所有结果集数据,并使用itext生成PDF.

public class StreamingPDFResultSetExtractor implements ResultSetExtractor<Void> {

    private final OutputStream os;
    private String tableName;

    /**
     * @param os the OutputStream to stream the PDF to
     */
    public StreamingPDFResultSetExtractor(final OutputStream os, final String tableName) {
        this.os = os;
        this.tableName = tableName;
    }

    @Override
    public Void extractData(final ResultSet rs) throws SQLException {
        // Creating a PdfDocument
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(os));
        // Creating a Document and setting page size
        Document document = new Document(pdfDoc, new PageSize(2384, 3370));
        // Adding a new page
        pdfDoc.addNewPage();
        final var rsmd = rs.getMetaData();
        final var columnCount = rsmd.getColumnCount();
        try {
            log.info("Generating PDF");
            Paragraph tablename = new Paragraph(tableName);
            tablename.setFontSize(20);
            // Add table
            Table table = new Table(columnCount);
            // Set width of table
            table.setWidth(UnitValue.createPercentValue(100)).setFixedLayout();
            table.setHorizontalAlignment(HorizontalAlignment.CENTER);
            table.setTextAlignment(TextAlignment.CENTER);
            // Header Font and color
            DeviceRgb hColor = new DeviceRgb(3, 148, 252);

            for (var i = 1; i <= columnCount; i++) {
                Cell hcell = new Cell();
                hcell.add(new Paragraph(rsmd.getColumnName(i)));
                hcell.setFontSize(14);
                hcell.setBackgroundColor(hColor);
                table.addHeaderCell(hcell);
            }
            while (rs.next()) {
                for (var i = 1; i <= columnCount; i++) {
                    final var value = rs.getObject(i);
                    String v = value == null ? "" : value.toString();
                        Cell cell = new Cell();
                        cell.add(new Paragraph(v));
                        table.addCell(cell);
                    }

                }
            }
            document.add(tablename);
            document.add(table);
            document.close();
            log.info("PDF generation complete");

        } catch (Exception ex) {

            log.error("Error occurred: {0}", ex);
        }
        return null;

    }
}

推荐答案

基本上可以使用另一个专门用于大型表的重载表类构造函数.如果将布尔值设置为true,它将布尔值作为一个参数,基本上可以减少内存占用.请参考iText 7 https://kb.itextpdf.com/home/it7kb/examples/large-tables中的这个示例,了解如何完成此操作

    // The second argument determines 'large table' functionality is used
    // It defines whether parts of the table will be written before all data is added.
    Table table = new Table(UnitValue.createPercentArray(5), true);

Java相关问答推荐

Java同步小服务器

让两个方法来回调用有缺点吗?

Spring Boot找不到Mapper bean

是否需要关闭Executors返回的执行器.newVirtualThreadPerTaskExecutor()?

ittext pdf延迟签名,签名无效

Java中是否有某种类型的池可以避免重复最近的算术运算?

Spring Boot 3.2.2中的@Inject和@Resource Remove

是否在允许数组元素为空时阻止 idea 为空性警告?

Spring @Value default无法计算表达式

将PNG转换为位图自定义十六进制字符串

如何在JUNIT测试中覆盖ExecutorService?

与IntArray相比,ArrayList<;Int>;对于大量元素的性能极差

错误:不兼容的类型:Double不能转换为Float

在一行中检索字符分隔字符串的第n个值

将BlockingQueue+守护程序线程替换为执行器

在ECLIPSE上的M1 Pro上运行JavaFX的问题

如何设计包含已知和未知键值对映射的Java类?

如何使用带有可选参数的类生成器?

验证没有';t work on Hibernate Entity';s字段

始终使用Spring Boot连接mongodb上的测试数据库