Skip to content

Wykład 3 - Aplikacje bazodanowe (JDBC) i GUI

  • Programy przechowujące i przetwarzające dane przez DBMS (system zarządzania bazą danych).
  • Zalety: trwałe przechowywanie, jednoczesny dostęp wielu użytkowników, bezpieczeństwo/integralność, analiza danych.
  • Komunikacja z bazą najczęściej przez zapytania SQL.

Aplikacja (Java, GUI + logika) → JDBC → DBMS → Baza danych. JDBC = warstwa pośrednicząca między JDK a DBMS.

  • Dane w tabelach: wiersz = rekord, kolumna = atrybut.
  • Relacje przez klucz obcy (foreign key); klucz główny (primary key) identyfikuje rekord.
  • Przykłady RDBMS: MySQL, PostgreSQL, Oracle, H2, SQLite.
Relacyjne (SQL) NoSQL
Model tabele dokumenty/grafy/klucz-wartość
Schemat ściśle określony często brak sztywnego
Język SQL zależny od systemu
Relacje klucze główne i obce dane zdenormalizowane
Skalowanie pionowe poziome
  • Create → INSERT, Read → SELECT, Update → UPDATE, Delete → DELETE.
  • JDBC (Java Database Connectivity) - standardowe API Javy, niezależne od konkretnego silnika bazy.
  • Funkcje pakietu: nawiązanie połączenia, wykonywanie zapytań SQL, przetwarzanie wyników, obsługa transakcji.
  1. JDBC-ODBC bridge - tłumaczy JDBC na ODBC; przestarzały, usunięty w Javie 8.
  2. Native API - używa natywnych bibliotek bazy, wymaga dodatkowych komponentów (np. Oracle OCI).
  3. Network protocol - komunikacja przez serwer pośredni tłumaczący JDBC na protokół bazy.
  4. Thin driver - napisany w Javie, łączy się bezpośrednio przez protokół sieciowy; najczęściej stosowany (np. jdbc:mysql://..., jdbc:h2:~/northwind).
Element Rola
DriverManager zarządza sterownikami, nawiązuje połączenia
Connection reprezentuje połączenie z bazą
Statement wykonuje zapytania SQL (proste, bez parametrów)
PreparedStatement zapytania parametryzowane (?)
ResultSet wynik zapytania SELECT
SQLException obsługa błędów bazy
  1. Nawiązanie połączenia → 2. Utworzenie Statement/PreparedStatement → 3. Wykonanie zapytania → 4. Odczyt ResultSet → 5. Zamknięcie połączenia.
  • getConnection(url) / getConnection(url, user, password) → zwraca Connection.
  • registerDriver(), deregisterDriver(), getDrivers().
  • createStatement(), prepareStatement(sql).
  • Transakcje: setAutoCommit(boolean), commit(), rollback(), close().
// try-with-resources automatycznie zamyka zasoby
try (Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) { /* ... */ }
} catch (SQLException e) { e.printStackTrace(); }
Statement PreparedStatement
Parametry brak placeholdery ?
SQL Injection podatny bezpieczny
Wielokrotne użycie nie tak (różne wartości)
  • executeQuery(sql) - dla SELECT, zwraca ResultSet.
  • executeUpdate(sql) - dla INSERT/UPDATE/DELETE i tworzenia tabel, zwraca liczbę zmodyfikowanych wierszy (int).
  • execute(sql) - uniwersalna, zwraca boolean (true = jest ResultSet, false = liczba wierszy).
  • Atak: wstrzyknięcie fragmentu SQL przez dane wejściowe użytkownika.
  • Klasyczny przykład - login ' OR '1'='1 powoduje warunek zawsze prawdziwy → zwrot wszystkich rekordów.
  • Rozwiązanie: PreparedStatement (oddziela kod SQL od danych).
  • Wynik SELECT, działa jak iterator po wierszach; next() przesuwa kursor, zwraca false na końcu.
  • Odczyt kolumny po nazwie (getInt("id")) lub indeksie (getString(2)); indeksy od 1.
  • Tryby typu kursora: TYPE_FORWARD_ONLY (domyślny), TYPE_SCROLL_INSENSITIVE, TYPE_SCROLL_SENSITIVE.
  • Tryby dostępu: CONCUR_READ_ONLY (domyślny), CONCUR_UPDATABLE (modyfikacja przez updateRow()).
  • Bazowy: SQLException (po nim dziedziczą pozostałe). Metody: getMessage(), getSQLState(), getErrorCode(), getNextException().
  • Pochodne: SQLTimeoutException, SQLTransientException (przejściowy, można ponowić), SQLNonTransientException (trwały), SQLIntegrityConstraintViolationException (np. duplikat klucza), SQLDataException, SQLFeatureNotSupportedException, SQLSyntaxErrorException.
  • Swing - klasyczne GUI w Java SE; komponent JTable.
  • JavaFX - nowsze GUI, CSS/FXML; komponent TableView.
  • Inne: SWT, Vaadin (webowe).
  • JTable wyświetla dane w wierszach/kolumnach, współpracuje z TableModel (przechowuje dane).
  • AbstractTableModel - abstrakcyjna klasa do własnych modeli; oddziela dane od widoku. Metody do nadpisania: getRowCount(), getColumnCount(), getValueAt(row,col), setValueAt(...), getColumnName(col).
  • DefaultTableModel - gotowa implementacja mapująca dane do JTable.
  • JScrollPane - umożliwia przewijanie tabeli; TableRowSorter - sortowanie.
  • Powiązany z ObservableListautomatyczne odświeżanie widoku przy zmianie danych.
  • Kolumna TableColumn powiązana z polem klasy przez PropertyValueFactory.
  • Zalety: nowoczesny wygląd, stylowanie CSS, lepsza integracja z DAO.
  • Oddziela logikę biznesową od operacji na bazie; wszystkie operacje CRUD dla encji w jednej klasie DAO.
  • Architektura warstwowa: GUI → Service → DAO → Database.
  • Zalety: separacja warstw, łatwe testowanie (mock DAO), wymienność bazy, reużywalność, czytelność.
  • H2 - lekka baza relacyjna w Javie; szybka, bez instalacji, działa w pamięci lub jako plik; idealna do nauki/testów. Konsola: java -jar h2*.jarhttp://localhost:8082.
  • Maven - narzędzie do zarządzania projektami Java: zależności, kompilacja, budowanie, standaryzacja struktury. Główny plik: pom.xml (POM = Project Object Model). Struktura: src/main/java, src/main/resources, src/test/java.
  • Northwind - przykładowa baza Microsoftu (edukacyjna); tabele: Customers, Orders, Employees, Products, Suppliers - powiązane kluczami obcymi.

Do zapamiętania: PreparedStatement chroni przed SQL Injection; executeQuery→SELECT, executeUpdate→INSERT/UPDATE/DELETE; ResultSet = iterator (indeks od 1); Swing=JTable, JavaFX=TableView+ObservableList; DAO oddziela logikę od bazy.