Úvod do JDBC

Java Top

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ

1. Prehľad

V tomto článku sa pozrieme na JDBC (Java Database Connectivity), čo je API na pripájanie a vykonávanie dotazov v databáze.

JDBC môže pracovať s ľubovoľnou databázou, pokiaľ sú k dispozícii správne ovládače.

2. Ovládače JDBC

Ovládač JDBC je implementácia rozhrania JDBC API používaná na pripojenie k určitému typu databázy. Existuje niekoľko typov ovládačov JDBC:

  • Typ 1 - obsahuje mapovanie na iné API na prístup k údajom; príkladom toho je ovládač JDBC-ODBC
  • Typ 2 - je implementácia, ktorá využíva knižnice cieľovej databázy na strane klienta; nazýva sa tiež natívny ovládač API
  • Typ 3 - používa middleware na konverziu hovorov JDBC na volania špecifické pre databázu; tiež známy ako ovládač sieťového protokolu
  • Typ 4 - pripojte sa priamo k databáze prevedením hovorov JDBC na volania špecifické pre databázu; známe ako ovládače databázového protokolu alebo tenké ovládače,

Najbežnejšie používaným typom je typ 4, pretože má tú výhodu, že je nezávislý na platforme. Pripojenie priamo k databázovému serveru poskytuje lepší výkon v porovnaní s inými typmi. Nevýhodou tohto typu ovládačov je, že je špecifický pre databázu - každá databáze má svoj vlastný špecifický protokol.

3. Pripojenie k databáze

Na pripojenie k databáze musíme jednoducho inicializovať ovládač a otvoriť databázové pripojenie.

3.1. Registrácia ovládača

Pre náš príklad použijeme ovládač databázového protokolu typu 4.

Pretože používame MySQL databázu, potrebujeme mysql-konektor-java závislosť:

 mysql mysql-konektor-java 6.0.6 

Ďalej zaregistrujeme ovládač pomocou Class.forName () metóda, ktorá dynamicky načíta triedu vodiča:

Class.forName ("com.mysql.cj.jdbc.Driver");

V starších verziách JDBC sme pred získaním spojenia museli najskôr inicializovať ovládač JDBC zavolaním Class.forName metóda. Od verzie JDBC 4.0 všetky ovládače, ktoré sa nachádzajú v triede cesty, sa načítajú automaticky. Preto to nebudeme potrebovať Class.forName súčasťou moderného prostredia.

3.2. Vytvára sa pripojenie

Na nadviazanie spojenia môžeme použiť getConnection () metóda DriverManager trieda. Táto metóda vyžaduje adresu URL pripojenia String parameter:

try (Connection con = DriverManager .getConnection ("jdbc: mysql: // localhost: 3306 / myDb", "user1", "pass")) {// tu použiť con}

Keďže Pripojenie je Automatické uzatváranie zdroj, mali by sme ho použiť vo vnútri a vyskúšajte zdroje blokovať.

Syntax adresy URL pripojenia závisí od typu použitej databázy. Pozrime sa na niekoľko príkladov:

jdbc: mysql: // localhost: 3306 / myDb? user = user1 & password = pass
jdbc: postgresql: // localhost / myDb
jdbc: hsqldb: mem: myDb

Na pripojenie k zadanému myDb databázy, budeme musieť vytvoriť databázu a užívateľa a pridať udeliť potrebný prístup:

VYTVORIŤ DATABÁZU myDb; VYTVORIŤ UŽÍVATEĽA „užívateľ1“ IDENTIFIKOVANÝ „priechodom“; UDELIŤ VŠETKO na myDb. * TO 'user1';

4. Vykonávanie príkazov SQL

Na odoslanie pokynov SQL do databázy môžeme použiť inštancie typu Vyhlásenie, Pripravené vyhlásenie, alebo Vyvolateľné vyhlásenie, ktoré môžeme získať pomocou Pripojenie objekt.

4.1. Vyhlásenie

The Vyhlásenie rozhranie obsahuje základné funkcie pre vykonávanie príkazov SQL.

Najskôr vytvorme a Vyhlásenie objekt:

try (Statement stmt = con.createStatement ()) {// tu použite stmt}

Opäť by sme mali pracovať s Vyhlásenies vo vnútri a vyskúšajte zdroje blok pre automatickú správu zdrojov.

Vykonanie inštrukcií SQL sa dá vykonať pomocou troch metód:

  • executeQuery () pre pokyny SELECT
  • executeUpdate () na aktualizáciu údajov alebo štruktúru databázy
  • vykonať () možno použiť pre obidva vyššie uvedené prípady, keď je výsledok neznámy

Použime vykonať () metóda na pridanie a študentov tabuľka do našej databázy:

Reťazec tableSql = "VYTVORIŤ TABUĽKU AK NEEXISTUJE zamestnancov" + "(emp_id int PRIMÁRNY KLÍČ AUTO_INCREMENT, meno varchar (30)," + "pozícia varchar (30), plat dvojnásobný)"; stmt.execute (tableSql);

Pri použití vykonať () spôsob aktualizácie údajov, potom stmt.getUpdateCount () metóda vráti počet ovplyvnených riadkov.

Ak je výsledok 0, potom to neovplyvnilo žiadne riadky, alebo išlo o príkaz na aktualizáciu štruktúry databázy.

Ak je hodnota -1, potom išlo o príkaz SELECT; potom môžeme výsledok získať pomocou stmt.getResultSet ().

Ďalej pridajme záznam do našej tabuľky pomocou executeUpdate () metóda:

Reťazec insertSql = "VLOŽTE DO ZAMESTNANCOV (meno, pozícia, plat)" + "HODNOTY ('john', 'vývojár', 2000)"; stmt.executeUpdate (insertSql);

Metóda vráti počet ovplyvnených riadkov pre príkaz, ktorý aktualizuje riadky, alebo 0 pre príkaz, ktorý aktualizuje databázovú štruktúru.

Záznamy môžeme získať z tabuľky pomocou príkazu executeQuery () metóda, ktorá vráti objekt typu Sada výsledkov:

Reťazec selectSql = "VYBERTE * OD zamestnancov"; try (ResultSet resultSet = stmt.executeQuery (selectSql)) {// tu použiť resultSet}

Mali by sme sa ubezpečiť, že sme zatvorili Sada výsledkov prípadoch po použití. V opačnom prípade môžeme nechať otvorený podkladový kurzor oveľa dlhšie, ako sme čakali. Za týmto účelom sa odporúča použiť a vyskúšajte zdroje blok, ako v našom príklade vyššie.

4.2. Pripravené vyhlásenie

Pripravené vyhlásenie objekty obsahujú predkompilované sekvencie SQL. Môžu mať jeden alebo viac parametrov označených otáznikom.

Vytvorme a Pripravené vyhlásenie ktorý aktualizuje záznamy v zamestnancov tabuľka na základe daných parametrov:

Reťazec updatePositionSql = "UPDATE zamestnanci NASTAVIŤ pozíciu =? KDE emp_id =?"; vyskúšať (PreparedStatement pstmt = con.prepareStatement (updatePositionSql)) {// tu použiť pstmt}

Ak chcete pridať parametre do Pripravené vyhlásenie, môžeme použiť jednoduché nastavovače - setX () - kde X je typ parametra a argumenty metódy sú poradie a hodnota parametra:

pstmt.setString (1, „hlavný vývojár“); pstmt.setInt (2, 1);

Príkaz sa vykonáva jednou z rovnakých troch metód, ktoré boli popísané vyššie: executeQuery (), executeUpdate (), execute () bez SQL String parameter:

int linesAffected = pstmt.executeUpdate ();

4.3. Vyvolateľné vyhlásenie

The Vyvolateľné vyhlásenie rozhranie umožňuje volanie uložených procedúr.

Ak chcete vytvoriť Vyvolateľné vyhlásenie objekt, môžeme použiť prepareCall () metóda Pripojenie:

Reťazec readySql = "{volať insertEmployee (?,?,?,?)}"; try (CallableStatement cstmt = con.prepareCall (readySql)) {// použite cstmt tu}

Nastavenie hodnôt vstupných parametrov pre uloženú procedúru sa robí ako v Pripravené vyhlásenie rozhranie, pomocou setX () metódy:

cstmt.setString (2, "ana"); cstmt.setString (3, "tester"); cstmt.setDouble (4, 2000);

Ak má uložená procedúra výstupné parametre, musíme ich pridať pomocou znaku registerOutParameter () metóda:

cstmt.registerOutParameter (1, Typ.INTEGER);

Potom vykonajme príkaz a získajme vrátenú hodnotu pomocou zodpovedajúceho getX () metóda:

cstmt.execute (); int new_id = cstmt.getInt (1);

Napríklad pre prácu potrebujeme vytvoriť uloženú procedúru v našej databáze MySql:

oddeľovač // VYTVORENIE POSTUPU insertEmployee (OUT emp_id int, IN emp_name varchar (30), IN position varchar (30), IN plate double) BEGIN INSERT INTO zaměstnanců (meno, pozícia, plat) HODNOTY (emp_name, pozícia, plat); SET emp_id = LAST_INSERT_ID (); KONIEC // oddeľovač;

The insertEmployee vyššie uvedený postup vloží nový záznam do súboru zamestnancov tabuľku pomocou daných parametrov a vrátiť ID nového záznamu v priečinku emp_id out parameter.

Aby bolo možné spustiť uloženú procedúru z Javy, musí mať užívateľ pripojenia prístup k metadátam uloženej procedúry. To sa dá dosiahnuť udelením práv používateľovi ku všetkým uloženým procedúram vo všetkých databázach:

UDELIŤ VŠETKO NA mysql.proc TO 'user1';

Prípadne môžeme otvoriť spojenie s nehnuteľnosťou noAccessToProcedureBodies nastavený na pravda:

con = DriverManager.getConnection ("jdbc: mysql: // localhost: 3306 / myDb? noAccessToProcedureBodies = true", "user1", "pass");

Toto informuje API JDBC, že používateľ nemá práva na čítanie metadát procedúry, aby vytvoril všetky parametre ako INOUT String parametre.

5. Analýza výsledkov dotazu

Po vykonaní dotazu je výsledok predstavovaný a Sada výsledkov objekt, ktorý má štruktúru podobnú tabuľke, s riadkami a stĺpcami.

5.1. Sada výsledkov Rozhranie

The Sada výsledkov používa Ďalšie() metóda na presun na ďalší riadok.

Najprv si vytvorme Zamestnanec triedy na uloženie našich získaných záznamov:

public class Employee {private int id; súkromné ​​meno reťazca; súkromná pozícia reťazca; dvojitý súkromný plat; // štandardný konštruktor, getre, setre}

Ďalej prejdime po Sada výsledkov a vytvorte Zamestnanec objekt pre každý záznam:

Reťazec selectSql = "VYBRAT * OD OD zamestnancov"; try (ResultSet resultSet = stmt.executeQuery (selectSql)) {Zoznam zamestnancov = nový ArrayList (); while (resultSet.next ()) {Employee emp = new Employee (); emp.setId (resultSet.getInt ("emp_id")); emp.setName (resultSet.getString ("meno")); emp.setPosition (resultSet.getString ("pozícia")); emp.setSalary (resultSet.getDouble ("plat")); zamestnanci.pridat (emp); }}

Získanie hodnoty pre každú bunku tabuľky je možné vykonať pomocou metód typu getX () kde X predstavuje typ údajov o bunke.

The getX () metódy môžu byť použité s int parameter predstavujúci poradie bunky, alebo a String parameter predstavujúci názov stĺpca. Posledná možnosť je vhodnejšia v prípade, že zmeníme poradie stĺpcov v dotaze.

5.2. Aktualizovateľné Sada výsledkov

Implicitne, a Sada výsledkov objektom je možné prechádzať iba dopredu a nemožno ho upravovať.

Ak chceme použiť Sada výsledkov aby sme aktualizovali údaje a prechádzali ich oboma smermi, musíme vytvoriť Vyhlásenie objekt s ďalšími parametrami:

stmt = con.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);

Na navigáciu v tomto type Sada výsledkov, môžeme použiť jednu z metód:

  • first (), last (), beforeFirst (), beforeLast () - presun na prvý alebo posledný riadok a Sada výsledkov alebo na riadok pred týmito
  • next (), previous () - navigácia vpred a vzad v Sada výsledkov
  • getRow () - na získanie aktuálneho čísla riadku
  • moveToInsertRow (), moveToCurrentRow () - presun na nový prázdny riadok, ktorý chcete vložiť, a späť na aktuálny riadok, ak je na novom riadku
  • absolútna (riadok int) - presunúť na zadaný riadok
  • relatívna (int nrRows) - na presun kurzora o daný počet riadkov

Aktualizuje sa Sada výsledkov je možné vykonať pomocou metód s formátom updateX () kde X je typ dát bunky. Tieto metódy iba aktualizujú Sada výsledkov objekt a nie databázové tabuľky.

Trvať na tom Sada výsledkov zmeny v databáze, musíme ďalej použiť jednu z metód:

  • updateRow () - zachovať zmeny v aktuálnom riadku v databáze
  • insertRow (), deleteRow () - pridať nový riadok alebo vymazať ten aktuálny z databázy
  • refreshRow () - osviežiť Sada výsledkov so zmenami v databáze
  • cancelRowUpdates () - zrušiť zmeny vykonané v aktuálnom riadku

Pozrime sa na príklad použitia niektorých z týchto metód aktualizáciou údajov v zamestnanec tabuľka:

try (Statement updatableStmt = con.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE)) {try (ResultSet updatableResultSet = updatableStmt.executeQuery (selectSql)) {updatableResultS) updatableResultSet.updateString ("meno", "značka"); updatableResultSet.updateString ("pozícia", "analytik"); updatableResultSet.updateDouble ("plat", 2000); updatableResultSet.insertRow (); }}

6. Analýza metadát

Rozhranie JDBC API umožňuje vyhľadávať informácie o databáze nazývané metadáta.

6.1. DatabaseMetadata

The DatabaseMetadata rozhranie možno použiť na získanie všeobecných informácií o databáze, ako sú tabuľky, uložené procedúry alebo dialekt SQL.

Poďme sa rýchlo pozrieť na to, ako môžeme načítať informácie z databázových tabuliek:

DatabaseMetaData dbmd = con.getMetaData (); ResultSet tablesResultSet = dbmd.getTables (null, null, "%", null); while (tablesResultSet.next ()) {LOG.info (tablesResultSet.getString ("TABLE_NAME")); }

6.2. ResultSetMetadata

Toto rozhranie možno použiť na vyhľadanie informácií o určitej osobe Sada výsledkov, ako je počet a názov jeho stĺpcov:

ResultSetMetaData rsmd = rs.getMetaData (); int nrColumns = rsmd.getColumnCount (); IntStream.range (1, nrColumns) .forEach (i -> {try {LOG.info (rsmd.getColumnName (i));} catch (SQLException e) {e.printStackTrace ();}});

7. Spracovanie transakcií

V predvolenom nastavení je každý príkaz SQL potvrdený hneď po dokončení. Je to však tiež možné programové riadenie transakcií.

To môže byť potrebné v prípadoch, keď chceme zachovať konzistenciu údajov, napríklad keď chceme transakciu zaviazať, iba ak bola predchádzajúca úspešne dokončená.

Najskôr musíme nastaviť autoCommit majetok Pripojenie do nepravdivé, potom použite spáchať () a rollback () metódy kontroly transakcie.

Pridajme druhé vyhlásenie o aktualizácii pre plat stĺpec za zamestnancom pozíciu aktualizácia stĺpca a oba tieto transakcie zabaľte. Týmto spôsobom bude plat aktualizovaný, iba ak bola pozícia úspešne aktualizovaná:

Reťazec updatePositionSql = "UPDATE zamestnanci NASTAVIŤ pozíciu =? KDE emp_id =?"; PreparedStatement pstmt = con.prepareStatement (updatePositionSql); pstmt.setString (1, „hlavný vývojár“); pstmt.setInt (2, 1); Reťazec updateSalarySql = "AKTUALIZOVAŤ zamestnancov NASTAVENÝ plat =? KDE emp_id =?"; PreparedStatement pstmt2 = con.prepareStatement (updateSalarySql); pstmt.setDouble (1 3000); pstmt.setInt (2, 1); boolean autoCommit = con.getAutoCommit (); try {con.setAutoCommit (false); pstmt.executeUpdate (); pstmt2.executeUpdate (); con.commit (); } chytit (SQLException exc) {con.rollback (); } konečne {con.setAutoCommit (autoCommit); }

Kvôli stručnosti vynecháme vyskúšajte zdroje bloky tu.

8. Uzavretie zdrojov

Keď to už nepoužívame, musíme uvoľniť databázové zdroje, musíme ukončiť pripojenie.

Môžeme to urobiť pomocou Zavrieť() API:

con.close ();

Ak však používame zdroj v a vyskúšajte zdroje blok, nemusíme volať Zavrieť() metóda výslovne ako vyskúšajte zdroje blok to za nás robí automaticky.

To isté platí pre Vyhlásenies, Pripravené vyhlásenies, Vyvolateľné vyhlásenies a Sada výsledkovs.

9. Záver

V tomto tutoriáli sme sa pozreli na základné informácie o práci s rozhraním JDBC API.

Celý zdrojový kód príkladov nájdete ako vždy na serveri GitHub.

Java dole

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ