Управление на данни с JavaFX

Графичните приложения, изградени с JavaFX, често се нуждаят от съхранение и извличане на информация – потребители, настройки, резултати или други структурирани данни. Тъй като JavaFX се фокусира единствено върху изграждането на потребителския интерфейс, за работата с бази данни се използват стандартните механизми на Java и външни технологии.

За тази цел най-често се комбинират JDBC като универсален интерфейс за достъп до бази данни и конкретна система за управление на бази данни, например H2. Тази комбинация позволява ясно разделение между визуалната част на приложението и логиката за работа с данни.

image

JDBC слой – връзка между Java и базата данни

JDBC (Java Database Connectivity) представлява стандартен интерфейс за работа с релационни бази данни в Java. Той дефинира начин за създаване на връзка, изпълнение на SQL заявки и обработка на резултатите, независимо от конкретната база данни.

Чрез JDBC приложението не комуникира директно с базата, а използва драйвер, който превежда заявките към конкретната система за управление на бази данни. Това позволява смяна на базата без промяна на бизнес логиката.

Основните обекти, с които работи JDBC, са:

  • Connection – активна връзка към базата данни
  • Statement / PreparedStatement – изпълнение на SQL заявки
  • ResultSet – резултат от SELECT заявка

H2 – вградена релационна база данни

За настолни Java приложения често се използват леки вградени бази данни. H2 е такава база, реализирана изцяло на Java, която се използва чрез JDBC и поддържа стандартен SQL синтаксис.

H2 може да работи във файл, което означава, че данните се съхраняват локално и се запазват между стартиранията на приложението. Това я прави подходяща за JavaFX приложения без нужда от външен сървър.

За да бъде използвана в Maven проект, е необходимо да се добави зависимостта към H2 JDBC драйвера.

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>2.4.240</version>
</dependency>

Създаване на връзка към базата данни

Връзката към базата се реализира в отделен клас, който централизира конфигурацията и позволява повторна употреба:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DatabaseConnection {

    private static final String URL = "jdbc:h2:./data/librarydb";
    private static final String USER = "sa";
    private static final String PASSWORD = "";

    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(URL, USER, PASSWORD);
    }
}

Тук се задават:

  • URL – пътя до H2 база в локален файл (./data/librarydb)
  • USER и PASSWORD – стандартни стойности за H2
  • Методът getConnection() връща готова връзка за използване от DAO или други класове.

Примерна задача: Каталог с книги

За демонстрация на управлението на данни да се създаде каталог с книги. Всеки запис да съдържа заглавие, автор, година на издаване и ISBN номер. Данните да се извличат от базата и да се визуализират с JavaFX интерфейс.

SQL структура на базата данни

CREATE TABLE books (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    author VARCHAR(255) NOT NULL,
    year INT,
    isbn VARCHAR(20)
);

Entity слой – клас Book

Всеки ред от таблицата books се представя в Java чрез entity клас. Този клас не съдържа логика за достъп до база данни и служи само за пренос и представяне на данните.

package bg.tu_varna.sit.ps.lab7;

public class Book {

    private int id;
    private String title;
    private String author;
    private int year;
    private String isbn;

    public Book(int id, String title, String author, int year, String isbn) {
        this.id = id;
        this.title = title;
        this.author = author;
        this.year = year;
        this.isbn = isbn;
    }

    public int getId() { return id; }
    public String getTitle() { return title; }
    public String getAuthor() { return author; }
    public int getYear() { return year; }
    public String getIsbn() { return isbn; }
}

Database Initializer

За да не се налага ръчно изпълнение на SQL скриптове, се създава клас DatabaseInitializer. Той създава таблица books и вкарва записи.

package bg.tu_varna.sit.ps.lab7;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

public class DatabaseInitializer {

    public static void initialize() {
        try (Connection conn = DatabaseConnection.getConnection();
             Statement stmt = conn.createStatement()) {

            // Създаваме таблицата books, ако не съществува
            stmt.execute("CREATE TABLE IF NOT EXISTS books (" +
                    "id INT AUTO_INCREMENT PRIMARY KEY, " +
                    "title VARCHAR(255) NOT NULL, " +
                    "author VARCHAR(255) NOT NULL, " +
                    "year INT, " +
                    "isbn VARCHAR(20))");

            // Вкарваме няколко примерни книги
            stmt.execute("INSERT INTO books (title, author, year, isbn) VALUES " +
                    "('Clean Code', 'Robert C. Martin', 2008, '9780132350884')," +
                    "('Effective Java', 'Joshua Bloch', 2018, '9780134685991')," +
                    "('Design Patterns', 'Gamma et al.', 1994, '9780201633610')");

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Какво се прави тук:

  • Създава се връзка чрез DatabaseConnection.getConnection(). Това гарантира, че всички SQL заявки ще се изпълнят в правилната база.
  • Създава се Statement, който позволява изпълнение на SQL код.
  • Създава се таблица само ако не съществува (IF NOT EXISTS), за да не се презаписват вече съществуващи данни.
  • Вкарват се начални записи чрез INSERT, което позволява веднага да се визуализират примерни данни в JavaFX приложението.

DAO слой – достъп до данните

DAO класът съдържа SQL заявките и отговаря за извличането на данни от базата. Той връща списък от entity обекти, които могат директно да бъдат използвани от JavaFX слоя.

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class BookDao {

    public List<Book> findAll() {
        List<Book> books = new ArrayList<>();
        String sql = "SELECT * FROM books";

        try (Connection conn = DatabaseConnection.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql);
             ResultSet rs = stmt.executeQuery()) {

            while (rs.next()) {
                Book book = new Book(
                        rs.getInt("id"),
                        rs.getString("title"),
                        rs.getString("author"),
                        rs.getInt("year"),
                        rs.getString("isbn")
                );
                books.add(book);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }

        return books;
    }
}

Визуализация с JavaFX

След като данните се извлекат от DAO, те се визуализират в графичния интерфейс чрез JavaFX TableView. Това позволява потребителят да вижда записите подредени в таблица. В зависимост от нуждите на приложението, могат да се използват и други контроли за визуализация на данните, като ListView, ComboBox или различни панели с текстови полета и етикети.

public class LibraryApplication extends Application {

    @Override
    public void start(Stage stage) {
        DatabaseInitializer.initialize(); // Създава се база и се вкарват примерни данни

        BookDao dao = new BookDao();
        List<Book> books = dao.findAll();

        TableView<Book> tableView = new TableView<>();
        tableView.setItems(FXCollections.observableArrayList(books));

        TableColumn<Book, String> titleCol = new TableColumn<>("Title");
        titleCol.setCellValueFactory(new PropertyValueFactory<>("title"));

        TableColumn<Book, String> authorCol = new TableColumn<>("Author");
        authorCol.setCellValueFactory(new PropertyValueFactory<>("author"));

        TableColumn<Book, Integer> yearCol = new TableColumn<>("Year");
        yearCol.setCellValueFactory(new PropertyValueFactory<>("year"));

        TableColumn<Book, String> isbnCol = new TableColumn<>("ISBN");
        isbnCol.setCellValueFactory(new PropertyValueFactory<>("isbn"));

        tableView.getColumns().addAll(titleCol, authorCol, yearCol, isbnCol);

        VBox layout = new VBox(10, tableView);
        layout.setPadding(new javafx.geometry.Insets(20));

        Scene scene = new Scene(layout, 600, 400);
        stage.setTitle("Library Catalog");
        stage.setScene(scene);
        stage.show();
    }

При успешно стартиране, трябва да се визуализира следният прозорец:

Screenshot 2026-02-03 223238


This site uses Just the Docs, a documentation theme for Jekyll.