Sprievodca rozhraním JDBC ResultSet

1. Prehľad

Rozhranie API Java Database Connectivity (JDBC) poskytuje prístup k databáze z aplikácie Java. Môžeme použiť JDBC na pripojenie k akejkoľvek databáze, pokiaľ je k dispozícii podporovaný ovládač JDBC.

The Sada výsledkov je tabuľka údajov generovaných vykonaním databázových dotazov. V tomto návode sa podrobnejšie pozrieme na Sada výsledkov API.

2. Generovanie a Sada výsledkov

Najskôr získame a Sada výsledkov volaním executeQuery () na akýkoľvek objekt vykonávajúci Vyhlásenie rozhranie. Obaja Pripravené vyhlásenie a Vyvolateľné vyhlásenie sú rozhrania rozhrania Vyhlásenie:

PreparedStatement pstmt = dbConnection.prepareStatement ("vybrať * od zamestnancov"); ResultSet rs = pstmt.executeQuery ();

The Sada výsledkov objekt udržuje kurzor, ktorý ukazuje na aktuálny riadok množiny výsledkov. Použijeme Ďalšie() na našom Sada výsledkov iterovať cez záznamy.

Ďalej budeme Použi getX () metódy pri iterácii výsledkov na načítanie hodnôt z databázových stĺpcov, kde X je údajový typ stĺpca. V skutočnosti poskytneme názvy stĺpcov databázy getX () metódy:

while (rs.next ()) {Názov reťazca = rs.getString ("meno"); Celé číslo empId = rs.getInt ("emp_id"); Dvojitý plat = rs.getDouble ("plat"); Pozícia reťazca = rs.getString ("pozícia"); } 

Podobne, indexové číslo stĺpca je možné použiť s getX () metódy namiesto názvu stĺpca. Indexové číslo je postupnosť stĺpcov v príkaze SQL select.

Ak príkaz select neuvádza názvy stĺpcov, indexové číslo je postupnosťou stĺpcov v tabuľke. Číslovanie indexov stĺpcov začína od jedného:

Celé číslo empId = rs.getInt (1); Názov reťazca = rs.getString (2); Pozícia reťazca = rs.getString (3); Dvojitý plat = rs.getDouble (4); 

3. Načítanie metadát z Sada výsledkov

V tejto časti sa dozvieme, ako načítať informácie o vlastnostiach a typoch stĺpcov v a Sada výsledkov.

Najprv použijeme getMetaData () metóda na našom Sada výsledkov získať ResultSetMetaData:

ResultSetMetaData metaData = rs.getMetaData ();

Ďalej poďme získať počet stĺpcov, ktoré sú v našom Sada výsledkov:

Celé číslo columnCount = metaData.getColumnCount ();

Ďalej môžeme na načítanie vlastností každého stĺpca použiť ktorúkoľvek z nasledujúcich metód na našom objekte metadát:

  • getColumnName (int columnNumber) pre získanie názvu stĺpca
  • getColumnLabel (int columnNumber) na prístup k štítku stĺpca, ktorý je uvedený za AS v dotaze SQL
  • getTableName (int columnNumber) pre získanie názvu tabuľky, do ktorej tento stĺpec patrí
  • getColumnClassName (int columnNumber) na získanie údajového typu Java stĺpca
  • getColumnTypeName (int columnNumber) získať údajový typ stĺpca v databáze
  • getColumnType (int columnNumber) získať údajový typ SQL stĺpca
  • isAutoIncrement (int columnNumber) označuje, či je stĺpec automatický prírastok
  • isCaseSensitive (int columnNumber) určuje, či má význam pre stĺpec
  • isSearchable (int columnNumber) navrhuje, či môžeme použiť stĺpec v kde klauzula dotazu SQL
  • isCurrency (int columnNumber) signalizuje, či stĺpec obsahuje peňažnú hodnotu
  • isNullable (int columnNumber) vracia nula ak stĺpec nemôže byť nulový, jeden - ak stĺpec môže obsahovať nulovú hodnotu, a - dva ak nullabilita stĺpca nie je známa
  • isSigned (int columnNumber) vracia pravda ak sú hodnoty v stĺpci podpísané, inak sa vráti nepravdivé

Poďme iterovať stĺpcami, aby sme získali ich vlastnosti:

for (int columnNumber = 1; columnNumber <= columnCount; columnNumber ++) {String catalogName = metaData.getCatalogName (columnNumber); Reťazec className = metaData.getColumnClassName (columnNumber); Označenie reťazca = metaData.getColumnLabel (columnNumber); Názov reťazca = metaData.getColumnName (columnNumber); Reťazec typeName = metaData.getColumnTypeName (columnNumber); int typ = metaData.getColumnType (columnNumber); Reťazec tableName = metaData.getTableName (columnNumber); Reťazec schemaName = metaData.getSchemaName (columnNumber); boolean isAutoIncrement = metaData.isAutoIncrement (columnNumber); boolean isCaseSensitive = metaData.isCaseSensitive (columnNumber); boolean isCurrency = metaData.isCurrency (columnNumber); boolean isDefiniteWritable = metaData.isDefinitelyWritable (columnNumber); boolean isReadOnly = metaData.isReadOnly (columnNumber); boolean isSearchable = metaData.isSearchable (columnNumber); boolean isReadable = metaData.isReadOnly (columnNumber); boolean isSigned = metaData.isSigned (columnNumber); boolean isWritable = metaData.isWritable (columnNumber); int nullable = metaData.isNullable (columnNumber); }

4. Navigácia v Sada výsledkov

Keď získame a Sada výsledkov, je poloha kurzora pred prvým riadkom. Navyše predvolene Sada výsledkov sa pohybuje iba smerom dopredu. Môžeme však použiť rolovateľné Sada výsledkov pre ďalšie možnosti navigácie.

V tejto časti si rozoberieme rôzne možnosti navigácie.

4.1. Sada výsledkov Typy

Sada výsledkov typ označuje, ako sa budeme pohybovať v množine údajov:

  • TYPE_FORWARD_ONLY - predvolená možnosť, v ktorej sa kurzor pohybuje od začiatku do konca
  • TYPE_SCROLL_INSENSITIVE - náš kurzor sa môže pohybovať v množine údajov v smere dopredu aj dozadu; ak dôjde k zmenám v podkladových údajoch pri pohybe v množine údajov, budú ignorované; množina údajov obsahuje údaje od času, keď databázový dotaz vráti výsledok
  • TYPE_SCROLL_SENSITIVE - podobne ako pri necitlivom type rolovania, avšak pre tento typ dátová sada okamžite odráža všetky zmeny základných údajov

Nie všetky databázy podporujú všetky Sada výsledkov typy. Poďme teda skontrolovať, či je typ podporovaný pomocou podporujeResultSetType na našom DatabaseMetaData objekt:

DatabaseMetaData dbmd = dbConnection.getMetaData (); boolean isSupported = dbmd.supportsResultSetType (ResultSet.TYPE_SCROLL_INSENSITIVE);

4.2. Posunovateľná sada výsledkov

Ak chcete získať rolovateľné Sada výsledkov, musíme počas prípravy Vyhlásenie.

Napríklad by sme získali rolovateľný Sada výsledkov použitím buď TYPE_SCROLL_INSENSITIVE alebo TYPE_SCROLL_SENSITIVE ako Sada výsledkov typ:

PreparedStatement pstmt = dbConnection.prepareStatement ("vybrať * od zamestnancov", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery (); 

4.3. Možnosti navigácie

Na posúvanie môžeme použiť ktorúkoľvek z nižšie uvedených možností Sada výsledkov:

  • Ďalšie() - postup do nasledujúceho riadku od aktuálnej polohy
  • predchádzajúca () - prejde na predchádzajúci riadok
  • najprv() - prejde do prvého riadku súboru Sada výsledkov
  • posledný () - skočí do posledného riadku
  • beforeFirst () - presunie sa na začiatok; volanie Ďalšie() na našom Sada výsledkov po zavolaní tejto metódy vráti prvý riadok z našej Sada výsledkov
  • afterLast () - skáče do konca; volanie previous () v našej ResultSet po vykonaní tejto metódy vráti posledný riadok z našej Sada výsledkov
  • relatívna (int numOfRows) - posunúť sa z aktuálnej polohy dopredu alebo dozadu o numOfRows
  • absolútne (int číslo riadku) - skočí do rowNumber špecifikované

Pozrime sa na niekoľko príkladov:

PreparedStatement pstmt = dbConnection.prepareStatement ("vybrať * od zamestnancov", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery (); while (rs.next ()) {// iterovať výsledkami od prvého po posledný} rs.beforeFirst (); // skočí späť do východiskového bodu, pred prvý riadok rs.afterLast (); // preskočí na koniec výsledkovej sady rs.first (); // prejde do prvého riadku rs.last (); // prejde na posledný riadok rs.absolute (2); // skočí do 2. riadku rs.relative (-1); // skočí na predchádzajúci riadok rs.relative (2); // skočí vpred o dva riadky, zatiaľ čo (rs.previous ()) {// iteruje z aktuálneho riadku na prvý riadok smerom dozadu} 

4.4. Sada výsledkov Počet riadkov

Poďme na to getRow () aby sme dostali aktuálne číslo riadku Sada výsledkov.

Najskôr prejdeme do posledného riadku Sada výsledkov a potom použite getRow () získať počet záznamov:

rs.last (); int rowCount = rs.getRow ();

5. Aktualizácia údajov v a Sada výsledkov

V predvolenom nastavení je Sada výsledkov je iba na čítanie. Môžeme však použiť aktualizovateľný Sada výsledkov na vloženie, aktualizáciu a odstránenie riadkov.

5.1. Sada výsledkov Súbežnosť

Režim súbežnosti označuje, či je náš Sada výsledkov môže aktualizovať údaje.

The CONCUR_READ_ONLY možnosť je predvolená a mala by sa použiť, ak nepotrebujeme aktualizovať údaje pomocou nášho Sada výsledkov.

Ak však potrebujeme aktualizovať údaje v našom Sada výsledkov, potom CONCUR_UPDATABLE možnosť by sa mala použiť.

Nie všetky databázy podporujú všetky režimy súbežnosti pre všetkých Sada výsledkov typy. Preto musíme skontrolovať, či je náš požadovaný typ a režim súbežnosti podporovaný pomocou podporujeResultSetConcurrency () metóda:

DatabaseMetaData dbmd = dbConnection.getMetaData (); boolean isSupported = dbmd.supportsResultSetConcurrency (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); 

5.2. Získanie aktualizovateľného Sada výsledkov

Na získanie aktualizovateľného Sada výsledkov, keď pripravujeme, musíme odovzdať ďalší parameter Vyhlásenie. Poďme na to CONCUR_UPDATABLE ako tretí parameter pri vytváraní výpisu:

PreparedStatement pstmt = dbConnection.prepareStatement ("vybrať * od zamestnancov", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery ();

5.3. Aktualizácia riadku

V tejto časti aktualizujeme riadok pomocou aktualizovateľných údajov Sada výsledkov vytvorené v predchádzajúcej časti.

Údaje môžeme aktualizovať za sebou volaním updateX () metódy, odovzdávanie názvov a hodnôt stĺpcov na aktualizáciu. Namiesto. Môžeme použiť akýkoľvek podporovaný dátový typ X v updateX () metóda.

Poďme aktualizovať „Plat“ stĺpec, ktorý je typu dvojitý:

rs.updateDouble ("plat", 1100,0);

Toto iba aktualizuje údaje v priečinku Sada výsledkov, ale úpravy ešte nie sú uložené späť do databázy.

Na záver si dáme zavolať updateRow () do uložte aktualizácie do databázy:

rs.updateRow (); 

Namiesto názvov stĺpcov môžeme index stĺpcov odovzdať znaku updateX () metódy. Je to podobné ako pri použití indexu stĺpca na získanie hodnôt pomocou getX () metódy. Predanie názvu stĺpca alebo indexu do updateX () metódy poskytujú rovnaký výsledok:

rs.updateDouble (4, 1100.0); rs.updateRow (); 

5.4. Vkladanie riadku

Teraz vložíme nový riadok pomocou našej aktualizovateľnej verzie Sada výsledkov.

Najprv použijeme moveToInsertRow () presunutím kurzora vložiť nový riadok:

rs.moveToInsertRow ();

Ďalej musíme zavolať updateX () metódy na pridanie informácií do riadku. Musíme poskytnúť údaje do všetkých stĺpcov v databázovej tabuľke. Ak neposkytneme údaje do každého stĺpca, použije sa predvolená hodnota stĺpca:

rs.updateString ("meno", "Venkat"); rs.updateString ("pozícia", "DBA"); rs.updateDouble ("plat", 925,0);

Potom sa ozvime insertRow () vložiť nový riadok do databázy:

rs.insertRow ();

Nakoniec použijeme moveToCurrentRow (). Týmto sa poloha kurzora vráti späť na riadok, v ktorom sme sa nachádzali predtým, ako sme začali vkladať nový riadok pomocou klávesu moveToInsertRow () metóda:

rs.moveToCurrentRow ();

5.5. Odstraňuje sa riadok

V tejto časti odstránime riadok pomocou našej aktualizovateľnej verzie Sada výsledkov.

Najskôr prejdeme k riadku, ktorý chceme odstrániť. Potom zavoláme deleteRow () spôsob odstránenia aktuálneho riadku:

rs.absolute (2); rs.deleteRow ();

6. Udržateľnosť

Udržateľnosť určuje, či je Sada výsledkov budú otvorené alebo uzavreté na konci databázovej transakcie.

6.1. Typy zadržateľnosti

Použite CLOSE_CURSORS_AT_COMMIT ak Sada výsledkov sa po potvrdení transakcie nevyžaduje.

Použite HOLD_CURSORS_OVER_COMMIT vytvoriť úložný priestor Sada výsledkov. Uchopiteľné Sada výsledkov nie je uzavretý ani po potvrdení transakcie s databázou.

Nie všetky databázy podporujú všetky typy uchovateľnosti.

Takže, poďme skontrolujte, či je podporovaný typ zadržania použitím podporujeResultSetHoldability () na našom DatabaseMetaData objekt. Potom získame predvolenú uchovateľnosť databázy pomocou getResultSetHoldability ():

boolean isCloseCursorSupported = dbmd.supportsResultSetHoldability (ResultSet.CLOSE_CURSORS_AT_COMMIT); boolean isOpenCursorSupported = dbmd.supportsResultSetHoldability (ResultSet.HOLD_CURSORS_OVER_COMMIT); boolean defaultHoldability = dbmd.getResultSetHoldability ();

6.2. Uchopiteľné Sada výsledkov

Na vytvorenie únosného materiálu Sada výsledkov, musíme špecifikovať únosnosť zadajte ako posledný parameter pri vytváraní a Vyhlásenie. Tento parameter je zadaný po režime súbežnosti.

Všimnite si, že ak používame Microsoft SQL Server (MSSQL), musíme nastaviť uchovateľnosť na databázovom pripojení, a nie na Sada výsledkov:

dbConnection.setHoldability (ResultSet.HOLD_CURSORS_OVER_COMMIT);

Pozrime sa na to v akcii. Najskôr vytvorme a Vyhlásenie, nastaviteľnosť pridržania na HOLD_CURSORS_OVER_COMMIT:

Príkaz pstmt = dbConnection.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT)

Poďme teraz aktualizovať riadok a načítať údaje. Je to podobné ako v prípade príkladu aktualizácie, o ktorom sme hovorili skôr, s tým rozdielom, že v ňom budeme pokračovať v iterácii Sada výsledkov po potvrdení transakcie aktualizácie do databázy. Toto funguje dobre v databázach MySQL aj MSSQL:

dbConnection.setAutoCommit (false); ResultSet rs = pstmt.executeQuery ("vybrať * od zamestnancov"); while (rs.next ()) {if (rs.getString ("name"). equalsIgnoreCase ("john")) {rs.updateString ("name", "John Doe"); rs.updateRow (); dbConnection.commit (); }} rs.last (); 

Stojí za zmienku, že MySQL podporuje iba HOLD_CURSORS_OVER_COMMIT. Takže, aj keď použijeme CLOSE_CURSORS_AT_COMMIT, bude to ignorované.

Databáza MSSQL podporuje CLOSE_CURSORS_AT_COMMIT. To znamená, že Sada výsledkov bude uzavreté, keď vykonáme transakciu. Výsledkom bol pokus o prístup k Sada výsledkov po vykonaní transakcie dôjde k chybe „Kurzor nie je otvorený“. Z tohto dôvodu nemôžeme načítať ďalšie záznamy Sada výsledkov.

7. Veľkosť načítania

Spravidla pri načítaní údajov do a Sada výsledkov, ovládače databázy rozhodujú o počte riadkov, ktoré sa majú z databázy načítať. Napríklad v databáze MySQL Sada výsledkov normálne načíta všetky záznamy do pamäte naraz.

Niekedy však možno budeme musieť narábať s veľkým počtom záznamov, ktoré sa nezmestia do našej pamäte JVM. V tomto prípade môžeme použiť vlastnosť veľkosti načítania buď na našom Vyhlásenie alebo Sada výsledkov objekty na obmedzenie počtu pôvodne vrátených záznamov.

Kedykoľvek sú potrebné ďalšie výsledky, Sada výsledkov načíta ďalšiu dávku záznamov z databázy. Pomocou vlastnosti veľkosť načítania môžeme poskytnúť ovládaču databázy návrh na počet riadkov, ktoré sa majú načítať za jednu databázovú cestu. Veľkosť načítania, ktorú zadáme, sa použije pri nasledujúcich výpadkoch databázy.

Ak neurčíme veľkosť načítania pre našu Sada výsledkov, potom veľkosť načítania súboru Vyhlásenie sa používa. Ak neurčíme veľkosť načítania ani pre jeden z nich Vyhlásenie alebo Sada výsledkov, potom sa použije predvolené nastavenie databázy.

7.1. Používanie veľkosti načítania v systéme Windows Vyhlásenie

Teraz sa pozrime na veľkosť načítania Vyhlásenie v akcii. Nastavíme veľkosť načítania súboru Vyhlásenie na 10 záznamov. Ak náš dopyt vráti 100 záznamov, bude tu 10 spiatočných cyklov databázy, zakaždým sa načíta 10 záznamov:

PreparedStatement pstmt = dbConnection.prepareStatement ("vybrať * od zamestnancov", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); pstmt.setFetchSize (10); ResultSet rs = pstmt.executeQuery (); while (rs.next ()) {// iterácia cez množinu výsledkov}

7.2. Používanie veľkosti načítania v systéme Windows Sada výsledkov

Poďme teraz zmeniť veľkosť načítania v našom predchádzajúcom príklade pomocou Sada výsledkov.

Najskôr použijeme veľkosť načítania na našom Vyhlásenie. To umožňuje naše Sada výsledkov na úvodné načítanie 10 záznamov po vykonaní dotazu.

Potom upravíme veľkosť načítania na serveri Sada výsledkov. Toto prepíše veľkosť načítania, ktorú sme predtým špecifikovali v našom Vyhlásenie. Takže všetky nasledujúce výlety načítajú 20 záznamov, kým sa nenačítajú všetky záznamy.

Výsledkom bude iba 6 databázových výjazdov na načítanie všetkých záznamov:

PreparedStatement pstmt = dbConnection.prepareStatement ("vybrať * od zamestnancov", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); pstmt.setFetchSize (10); ResultSet rs = pstmt.executeQuery (); rs.setFetchSize (20); while (rs.next ()) {// iterácia cez množinu výsledkov}

Nakoniec uvidíme, ako upraviť veľkosť načítania súboru Sada výsledkov pri opakovaní výsledkov.

Podobne ako v predchádzajúcom príklade, najskôr nastavíme veľkosť načítania na 10 na našom Vyhlásenie. Naše prvé 3 výlety databázou teda načítajú 10 záznamov za každú cestu.

A potom upravíme veľkosť načítania na našom Sada výsledkov na 20 pri čítaní 30. záznamu. Nasledujúce 4 cesty teda načítajú 20 záznamov za každú cestu.

Na načítanie všetkých 100 záznamov preto budeme potrebovať 7 databázových výletov:

PreparedStatement pstmt = dbConnection.prepareStatement ("vybrať * od zamestnancov", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); pstmt.setFetchSize (10); ResultSet rs = pstmt.executeQuery (); int riadokPočet = 0; while (rs.next ()) {// iterovať cez výslednú sadu if (rowCount == 30) {rs.setFetchSize (20); } rowCount ++; }

8. Záver

V tomto článku sme videli, ako používať Sada výsledkov API na načítanie a aktualizáciu údajov z databázy. Niektoré z pokročilých funkcií, o ktorých sme hovorili, závisia od databázy, ktorú používame. Predtým, ako ich začneme používať, musíme skontrolovať podporu týchto funkcií.

Ako vždy, kód je k dispozícii na GitHub.