IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

3. diel - Databázy v Java JDBC - Výpis dát a parametre

V minulom dieli nášho seriálu tutoriálov o databázach v Jave sme si pripravili databázu s testovacími dátami. V dnešnom dieli sa k nej v Jave pripojíme a budeme z nej čítať hodnoty.

Vytvorenie projektu

Vytvoríme si novú Java application s názvom slovníček. V oknu Projects na projekt klikneme pravým a zvolíme Properties.

V kategóriách vľavo vyberieme Libraries a klikneme na Add Library.

Pridanie MySQL ovládača do Java projektu - Databázy v Jave - JDBC

V dialógu vyberieme MySQL JDBC Driver a potvrdíme. Keď budete chcieť pracovať s akoukoľvek databázou pomocou JDBC, je vždy potrebné pridať týmto spôsobom príslušný Connector. Ten sa dá stiahnuť ako súbor .jar na webe výrobcu databázy a pridať rovnakým spôsobom pomocou tlačidla Add JAR.

Pridanie MySQL ovládača do Java projektu - Databázy v Jave - JDBC

Načítanie ovládača

V minulosti bolo treba JDBC ovládač pred použitím načítať. Robilo sa to týmto spôsobom:

try {
    Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException ex) {
    System.out.println("Chyba při načtení databázového ovladače");
}

Java si dnes už ovládač načíta sama a tento kód teda netreba. Uvádzam ho len z toho dôvodu, keby ste ho videli v starších projektoch alebo zastaraných tutoriáloch.

Connection, PreparedStatement a ResultSet

S databázou budeme pracovať pomocou svätej trojice tried Connection, PreparedStatement a ResultSet. Všetky sa nachádzajú v balíčku java.sql.

Connection

Connection je databázové spojenie. To je nutné vytvoriť predtým, než sa databáza na niečo spýtame. Pri jeho vytváraní uvedieme tzv. Connection string. To je reťazec obsahujúci meno databázového ovládača, URL servera, kde databázy beží, ďalej názov databázy, užívateľské meno a heslo.

Vytvorenie novej inštancie spojenie bude v našom prípade vyzerať takto:

Connection spojeni = DriverManager.getConnection("jdbc:mysql://localhost/slovnicek_db?user=root&password=")

PreparedStatement

PreparedStatement je databázový dotaz. Pri vytvorení inštancie zadávame SQL kód, ktorý chceme na databázu spustiť. Java obsahuje tiež triedu Statement, ktorá sa od PreparedStatement líši tým, že nemôže obsahovať parametre (o tom ďalej).

V našom prípade si vytvoríme nasledujúce inštanciu dotazu:

PreparedStatement dotaz = spojeni.prepareStatement("SELECT * FROM slovo")

Všimnite si, že sa otázka vytvára cez inštanciu spojenie.

Patrilo by sa vysvetliť aj samotný SQL dotaz. Príkazom SELECT hovoríme, že chceme z databázovej tabuľky vybrať dáta. Hviezdička označuje, že u výsledných riadkov chceme vybrať hodnoty zo všetkých stĺpcov. FROM slovo označuje, že vyberáme z tabuľky slovo. Otázka teda vyberie všetky hodnoty všetkých slov.

ResultSet

ResultSet je kolekcia výsledkov, ktoré vrátil nejaký SQL dotaz. ResultSet naplnený výsledky SQL príkazu SELECT získame pomocou metódy executeQuery () na inštanciu dotazu.

ResultSet vysledky = dotaz.executeQuery();

Uzatváranie spojenia

Ak ste v Jave už pracovali so súbormi, nebude pre vás žiadnym prekvapením, že aj databázové spojenie sa musí uzavrieť. Malým prekvapením však môže byť, že sa musíme postarať o správne uzatvorenie všetkých 3 databázových objektov. Keby sme to neurobili, zostalo by spojenie otvorené a server by sa za nejakú dobu zahltil.

Najjednoduchší spôsob je vytvoriť objekty v bloku try-with-resources (TWR). Akonáhle Java tento blok kódu opustí, sama sa postará o uzavretí inštancií, ktoré sú v deklarácii bloku vytvorené.

try (Connection spojeni = DriverManager.getConnection("jdbc:mysql://localhost/slovnicek_db?user=root&password=");
    PreparedStatement dotaz = spojeni.prepareStatement("SELECT * FROM slovo");
    ResultSet vysledky = dotaz.executeQuery();) {

} catch (SQLException ex) {
    System.out.println("Chyba při komunikaci s databází");
}

Ak sa niečo pokazí, informujeme o tom užívateľa chybovým hlásením. Pri ladení blok catch zakomentujte, aby ste mohli na chyby reagovať a kód opraviť.

Výpis výsledkov

V premennej vysledky máme už načítané slovíčka z databázy. Zostáva je len vypísať. ResultSet na sebe obsahuje metódu next (). Tá presunie aktuálnu pozíciu v kolekcii na ďalší prvok alebo vráti false v prípade, že sme na konci výsledkov. Next je nutné zavolať minimálne raz, ak chceme z výsledkov niečo čítať.

K samotnému čítanie hodnoty na aktuálnom riadku výsledkov slúži metódy začínajúcich get. Nájdeme tu getInt (), getString (), getDate () a ďalšie. Metódam môžeme dať ako parameter buď názov stĺpca alebo jeho číselný index. U číselného indexu pozor, prvý stĺpec má index 1.

while (vysledky.next()) {
    int id = vysledky.getInt(1);
    String cesky = vysledky.getString("cesky");
    String anglicky = vysledky.getString("anglicky");
    System.out.println("Id: " + id + ", česky: " + cesky + ", anglicky: " + anglicky);
}

Kódom vyššie iterujeme nad výsledkami, získavame ich parametre a tie potom vypisujeme do konzoly. Ukážme si ešte kompletnú kód aplikácie:

try (Connection spojeni = DriverManager.getConnection("jdbc:mysql://localhost/slovnicek_db?user=root&password=a");
    PreparedStatement dotaz = spojeni.prepareStatement("SELECT * FROM slovo");
    ResultSet vysledky = dotaz.executeQuery();) {

    while (vysledky.next()) {
        int id = vysledky.getInt(1);
        String cesky = vysledky.getString("cesky");
        String anglicky = vysledky.getString("anglicky");
        System.out.println("Id: " + id + ", česky: " + cesky + ", anglicky: " + anglicky);
    }

} catch (SQLException ex) {
    System.out.println("Chyba při komunikaci s databází");
}

Môžete si skúsiť, že aplikácia naozaj vypíše všetky slovíčka z databázy:

Čítanie z MySQL databázy pomocou JDBC v Jave - Databázy v Jave - JDBC

Odovzdávanie parametrov

Dovedie aplikáciu naozaj do podoby slovníčku. Užívateľa necháme zadať slovíčko v angličtine a to mu následne preložíme do slovenčiny.

Sql injekcie

SQL dotaz by mal teraz vybrať len určitý riadok, je do neho teda potrebné dodať podmienky. To docielime pomocou klauzuly WHERE. Naivne by sme mohli vložiť slovíčko od užívateľa priamo do tela SQL dotazu:

// Tento kód je nebezpečný
Scanner scanner = new Scanner(System.in, "Windows-1250");
System.out.println("Zadej anglické slovíčko k překladu:");
String anglicky = scanner.nextLine();
try (Connection spojeni = DriverManager.getConnection("jdbc:mysql://localhost/slovnicek_db?user=root&password=");
    PreparedStatement dotaz = spojeni.prepareStatement("SELECT cesky FROM slovo WHERE anglicky=\"" + anglicky + "\"");
    ResultSet vysledky = dotaz.executeQuery();) {

    vysledky.next();
    String cesky = vysledky.getString("cesky");
    System.out.println("Překlad " + anglicky + ": " + cesky);
} catch (SQLException ex) {
    System.out.println("Chyba při komunikaci s databází");
}

výsledok:

MySQL slovníček v Jave - Databázy v Jave - JDBC

Kód sa príliš nezmenil. V SQL dotazu už nevyberáme všetky stĺpce, ale iba stĺpec cesky. Okrem toho nám tu pribudla podmienka WHERE. Výsledky už nenačítajú vo while cykle, pretože nás zaujíma iba jeden.

Hoci sa zdá, že aplikácia funguje perfektne, opak je pravdou. Čokoľvek používateľ zadá sa vloží priamo do SQL dotazu. Čo sa stane, keď zadá napr. Nasledujúce reťazec?

"; DROP TABLE slovo --

Na databázu sa spustí príkaz k vymazaniu tabuľky a máme po dátach. To je ešte ten lepší prípad, šikovnejší používateľ by nám cez slovníček mohol treba vyťahať heslá používateľov z inej tabuľky. A to už by bol problém. Verte alebo nie, ale používatelia také vstupy naozaj zadávajú a vaše aplikácie sa im musí brániť. Tejto technike útoku sa hovorí SQL injection, pretože sa vkladá cudzie SQL kód do nášho dotazu.

Odovzdávanie parametrov

Celý problém je samozrejme v tom, že vkladáme vstup od užívateľa priamo do SQL dotazu. Keďže nikdy nemôžeme vedieť, či sa v nejakej premennej môže vyskytnúť niečo, čo užívateľ zadal, upravme náš problém na: vloženie ktorejkoľvek premenné do SQL dotazu je veľké bezpečnostné riziko. V minulosti sa premenné ošetrovali špeciálnou funkciou, ktorá tzv. Zescapovala nebezpečné znaky (najmä úvodzovky). Najbezpečnejšie je však používať tzv. Prepared statements.

Prepared statement je dotaz, ktorý obsahuje namiesto parametrov zástupné znaky, najčastejšie otázniky. Samotné hodnoty sa do dotazu dosadí oddelene a sama databázy sa postará o ich bezpečné vloženie do dotazu.

Prepíšme našu aplikáciu tak, aby používala parametrizované otázky:

Scanner scanner = new Scanner(System.in, "Windows-1250");
System.out.println("Zadej anglické slovíčko k překladu:");
String anglicky = scanner.nextLine();
try (Connection spojeni = DriverManager.getConnection("jdbc:mysql://localhost/slovnicek_db?user=root&password=");
    PreparedStatement dotaz = spojeni.prepareStatement("SELECT cesky FROM slovo WHERE anglicky=?");) {
    dotaz.setString(1, anglicky);
    try (ResultSet vysledky = dotaz.executeQuery()) {
        vysledky.next();
        String cesky = vysledky.getString("cesky");
        System.out.println("Překlad " + anglicky + ": " + cesky);
    }
} catch (SQLException ex) {
    System.out.println("Chyba při komunikaci s databází");
}

Všimnite si otáznika v dotaze a volanie metódy setString (), ktorá nastaví prvý parameter v dotaze na daný reťazec. Samozrejme tu nájdeme aj metódy pre ďalšie dátové typy. Naša aplikácia je teraz bezpečná.

Nabudúce si ukážeme ako záznamy v databáze editovať. Dnešný projekt je so zdrojovým kódom ako vždy k stiahnutiu nižšie.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 656x (18.28 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Predchádzajúci článok
Návrh MySQL databázy v NetBeans IDE
Všetky články v sekcii
Databázy v Jave - JDBC
Preskočiť článok
(neodporúčame)
Databázy v Java JDBC - INSERT, UPDATE, DELETE a COUNT
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
2 hlasov
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity