Java GUI with JTable and Database

"JTable is Swing's component for displaying data in rows and columns — a natural fit for database-backed applications where records are displayed and updated in real time."- Claude 2026

JTable and Database-Backed GUIs

A JTable displays data in a grid of rows and columns, similar to a spreadsheet. It is the natural Swing component for showing database query results — each row in the table corresponds to a row in the database, and each column corresponds to a field.

Like JList, a JTable uses a model to hold its data. The standard model is DefaultTableModel, which lets you define column headers and add rows of data programmatically. When the model is updated, the table display updates automatically.

JTable Key Concepts

DefaultTableModel

Holds the table's data — column names and rows of values. Pass it to the JTable constructor and update it to refresh the display.

tableModel.addRow(Object[])

Appends a row of values to the table. Each element in the array corresponds to a column.

tableModel.setRowCount(0)

Clears all rows from the table. Useful for refreshing the display after a database change.

table.getSelectedRow()

Returns the index of the currently selected row, or -1 if nothing is selected.

tableModel.getValueAt(row, col)

Returns the value in a specific cell, useful for reading a selected row's data.

JScrollPane

Always wrap a JTable in a JScrollPane so column headers remain visible and the table can scroll when rows exceed the visible area.

Application Overview

The complete application is a Party Roster GUI backed by a SQLite database. It demonstrates the full loop: connecting to the database on startup, loading records into a JTable, and allowing the user to add and delete records with the table refreshing automatically after each change.

The interface uses a BorderLayout with three regions:

Complete GUI Application
The tabs below contain the full application code and a separate script to create and populate the SQLite database used for the demo. Run the database setup script first, then compile and run the GUI.
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import java.sql.*;

public class PartyRoster extends JFrame {

    static final String URL = "jdbc:sqlite:game.db";

    private DefaultTableModel tableModel;
    private JTable table;
    private JTextField nameField;
    private JComboBox<String> classCombo;
    private JButton addButton, deleteButton;

    public PartyRoster() {
        setTitle("Party Roster");
        setSize(550, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout(5, 5));

        // --- Table (Center) ---
        String[] columns = {"ID", "Name", "Class"};
        tableModel = new DefaultTableModel(columns, 0) {
            // Make cells non-editable
            public boolean isCellEditable(int row, int col) { return false; }
        };

        table = new JTable(tableModel);
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.getColumnModel().getColumn(0).setMaxWidth(50);
        add(new JScrollPane(table), BorderLayout.CENTER);

        // --- Input Form (North) ---
        JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        nameField  = new JTextField(12);
        classCombo = new JComboBox<>(new String[]{"Warrior", "Mage", "Archer", "Rogue"});
        addButton  = new JButton("Add");

        inputPanel.add(new JLabel("Name:"));
        inputPanel.add(nameField);
        inputPanel.add(new JLabel("Class:"));
        inputPanel.add(classCombo);
        inputPanel.add(addButton);
        add(inputPanel, BorderLayout.NORTH);

        // --- Delete Button (South) ---
        deleteButton = new JButton("Delete Selected");
        add(deleteButton, BorderLayout.SOUTH);

        // --- Event Handlers ---
        addButton.addActionListener(e -> {
            String name      = nameField.getText().trim();
            String charClass = (String) classCombo.getSelectedItem();
            if (!name.isEmpty()) {
                insertCharacter(name, charClass);
                nameField.setText("");
                loadTable();
            }
        });

        deleteButton.addActionListener(e -> {
            int row = table.getSelectedRow();
            if (row != -1) {
                int id = (int) tableModel.getValueAt(row, 0);
                deleteCharacter(id);
                loadTable();
            }
        });

        // Load data from database on startup
        loadTable();
        setVisible(true);
    }

    private void loadTable() {
        tableModel.setRowCount(0);
        try (Connection conn = DriverManager.getConnection(URL);
             PreparedStatement stmt = conn.prepareStatement("SELECT * FROM characters");
             ResultSet rs = stmt.executeQuery()) {

            while (rs.next()) {
                tableModel.addRow(new Object[]{
                    rs.getInt("id"),
                    rs.getString("name"),
                    rs.getString("class")
                });
            }
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(this, "Error loading data: " + e.getMessage());
        }
    }

    private void insertCharacter(String name, String charClass) {
        String sql = "INSERT INTO characters (name, class) VALUES (?, ?)";
        try (Connection conn = DriverManager.getConnection(URL);
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setString(1, name);
            stmt.setString(2, charClass);
            stmt.executeUpdate();
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(this, "Error inserting: " + e.getMessage());
        }
    }

    private void deleteCharacter(int id) {
        String sql = "DELETE FROM characters WHERE id = ?";
        try (Connection conn = DriverManager.getConnection(URL);
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setInt(1, id);
            stmt.executeUpdate();
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(this, "Error deleting: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new PartyRoster());
    }

}
import java.sql.*;

public class SetupDB {

    static final String URL = "jdbc:sqlite:game.db";

    public static void main(String[] args) {

        try (Connection conn = DriverManager.getConnection(URL);
             Statement stmt  = conn.createStatement()) {

            // Create table
            stmt.execute("""
                CREATE TABLE IF NOT EXISTS characters (
                    id    INTEGER PRIMARY KEY AUTOINCREMENT,
                    name  TEXT NOT NULL,
                    class TEXT NOT NULL
                )
            """);

            // Clear any existing data for a clean demo
            stmt.execute("DELETE FROM characters");

            // Insert sample characters
            stmt.execute("INSERT INTO characters (name, class) VALUES ('Hero',   'Warrior')");
            stmt.execute("INSERT INTO characters (name, class) VALUES ('Zara',   'Mage')");
            stmt.execute("INSERT INTO characters (name, class) VALUES ('Fletch', 'Archer')");
            stmt.execute("INSERT INTO characters (name, class) VALUES ('Dray',   'Rogue')");

            System.out.println("Database created: game.db");
            System.out.println("Table created: characters");
            System.out.println("Sample data inserted.");

        } catch (SQLException e) {
            System.out.println("Setup failed: " + e.getMessage());
        }

    }

}
Running the Application
  1. Download and install the Java Development Kit (JDK) if you haven't already.
  2. Download the SQLite JDBC driver jar from github.com/xerial/sqlite-jdbc/releases and place it in your project folder.
  3. Save both SetupDB.java and PartyRoster.java in the same folder as the jar.
  4. Compile both files:
    javac SetupDB.java PartyRoster.java
  5. Run the database setup script first (remember to update your jdbc version as needed):
    java -cp .:sqlite-jdbc-3.51.3.0.jar SetupDB
  6. Then run the GUI application:
    java -cp .:sqlite-jdbc-3.51.3.0.jar PartyRoster

On Windows, replace : with ; in the classpath.

→ This page was created with help from Claude AI.