在Java NetBeans中基于双数据库表顺序行生成PDF报表
Got it, let's break down how to build this PDF report feature in Java NetBeans step by step. Here's a practical approach that fits your requirement of fetching data in sequence from Table A and matching Table B records:
First, pick a reliable PDF library—iText 7 is a great choice for this task, as it’s well-documented and integrates smoothly with NetBeans.
- For Maven projects: Add this to your
pom.xmlto pull in the dependencies automatically:
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itext7-core</artifactId> <version>7.2.5</version> </dependency>
- For non-Maven projects: Download the iText 7 core JARs, then right-click your NetBeans project →
Properties→Libraries→Add JAR/Folderto include them.
Don’t forget to add your database’s JDBC driver (like MySQL Connector/J for MySQL) to the project libraries too—you’ll need it to connect to your database.
The core logic here is to loop through Table A row by row, then pull matching records from Table B for each entry. We’ll use JDBC for database access, and a simple model class to hold combined data from both tables.
1. Create a Data Model Class
This helps organize the data from both tables:
class ReportEntry { // Replace these fields with your actual table columns private String tableAId; private String tableAName; private String tableBDetails; private String tableBValue; // Constructor public ReportEntry(String aId, String aName, String bDetails, String bValue) { this.tableAId = aId; this.tableAName = aName; this.tableBDetails = bDetails; this.tableBValue = bValue; } // Getters (required to access data in PDF generation) public String getTableAId() { return tableAId; } public String getTableAName() { return tableAName; } public String getTableBDetails() { return tableBDetails; } public String getTableBValue() { return tableBValue; } }
2. Data Fetching Logic
Use try-with-resources to auto-close database connections and avoid resource leaks:
import java.sql.*; import java.util.ArrayList; import java.util.List; public class DataFetcher { // Replace with your database credentials private static final String DB_URL = "jdbc:mysql://localhost:3306/your_db_name"; private static final String DB_USER = "your_username"; private static final String DB_PASS = "your_password"; public List<ReportEntry> fetchSequentialData() throws SQLException { List<ReportEntry> reportEntries = new ArrayList<>(); // Connect to DB and fetch Table A rows in order try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS); PreparedStatement stmtA = conn.prepareStatement("SELECT * FROM TableA ORDER BY id"); // Order to get row 1, 2, etc. ResultSet rsA = stmtA.executeQuery()) { while (rsA.next()) { // Extract data from current Table A row String aId = rsA.getString("id"); // Assume "id" is the matching field with Table B String aName = rsA.getString("name"); // Fetch matching records from Table B try (PreparedStatement stmtB = conn.prepareStatement("SELECT * FROM TableB WHERE a_id = ?")) { stmtB.setString(1, aId); try (ResultSet rsB = stmtB.executeQuery()) { // Handle multiple matching rows in Table B if (rsB.next()) { do { String bDetails = rsB.getString("details"); String bValue = rsB.getString("value"); reportEntries.add(new ReportEntry(aId, aName, bDetails, bValue)); } while (rsB.next()); } else { // Add placeholder if no matching data in Table B reportEntries.add(new ReportEntry(aId, aName, "No matching data", "N/A")); } } } } } return reportEntries; } }
Note: Adjust the column names (id, name, etc.) and ORDER BY clause to match your actual table structure—this ensures you get Table A rows in the exact sequence you need.
Now take the fetched data and build the PDF using iText 7. Here’s a complete implementation:
import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfWriter; import com.itextpdf.layout.Document; import com.itextpdf.layout.element.Paragraph; import com.itextpdf.layout.element.Table; import com.itextpdf.layout.properties.UnitValue; import java.io.FileNotFoundException; import java.sql.SQLException; import java.util.List; public class PdfReportGenerator { public void createReport(String outputFilePath) throws FileNotFoundException, SQLException { DataFetcher dataFetcher = new DataFetcher(); List<ReportEntry> reportData = dataFetcher.fetchSequentialData(); // Initialize PDF writer and document PdfWriter writer = new PdfWriter(outputFilePath); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); // Add report title doc.add(new Paragraph("Combined Table A & Table B Report").setBold().setFontSize(16)); // Create a table to display data Table table = new Table(UnitValue.createPercentArray(4)).useAllAvailableWidth(); table.addHeaderCell("Table A ID"); table.addHeaderCell("Table A Name"); table.addHeaderCell("Table B Details"); table.addHeaderCell("Table B Value"); // Populate the table with data for (ReportEntry entry : reportData) { table.addCell(entry.getTableAId()); table.addCell(entry.getTableAName()); table.addCell(entry.getTableBDetails()); table.addCell(entry.getTableBValue()); } doc.add(table); doc.close(); System.out.println("Report generated at: " + outputFilePath); } // Test the generator (call this from a button action or main method) public static void main(String[] args) { try { new PdfReportGenerator().createReport("C:/Reports/combined_report.pdf"); } catch (Exception e) { e.printStackTrace(); } } }
If you’re building a Swing desktop app, add a button to trigger report generation:
import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class ReportUI extends JFrame { public ReportUI() { JButton generateBtn = new JButton("Generate PDF Report"); generateBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { new PdfReportGenerator().createReport("C:/Reports/your_report.pdf"); JOptionPane.showMessageDialog(null, "Report generated successfully!"); } catch (Exception ex) { JOptionPane.showMessageDialog(null, "Error generating report: " + ex.getMessage()); ex.printStackTrace(); } } }); add(generateBtn); setSize(300, 100); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } public static void main(String[] args) { new ReportUI(); } }
- Database Connection Issues: Double-check your JDBC URL, username, and password. Ensure your database server is running.
- PDF Generation Errors: Verify all iText JARs are included in your project. Check file permissions for the output folder.
- Row Order: Always use
ORDER BYin your Table A query—databases don’t guarantee row order unless explicitly specified.
内容的提问来源于stack exchange,提问作者Ahmad Tijjani Isah

