Útmutató a JDBC ResultSet interfészhez

1. Áttekintés

A Java Database Connectivity (JDBC) API hozzáférést biztosít az adatbázishoz egy Java alkalmazásból. A JDBC segítségével bármelyik adatbázishoz csatlakozhatunk, amennyiben a támogatott JDBC illesztőprogram rendelkezésre áll.

A ResultSet az adatbázis-lekérdezések végrehajtásával létrehozott adatok táblázata. Ebben az oktatóanyagban mélyebben megvizsgáljuk a ResultSet API.

2. A. Generálása ResultSet

Először a ResultSet hívással executeQuery () bármely objektumon, amely a Nyilatkozat felület. Mind a PreparedStatement és a CallableStatement alinterfészei Nyilatkozat:

PreparedStatement pstmt = dbConnection.prepareStatement ("válasszon * az alkalmazottak közül"); ResultSet rs = pstmt.executeQuery ();

A ResultSet object fenntart egy kurzort, amely az eredményhalmaz aktuális sorára mutat. Majd használjuk következő() miénken ResultSet hogy a bejegyzések között iteráljon.

Ezután megtesszük használja a getX () metódusokat, miközben az eredmények között végigvezetik az értékeket az adatbázis oszlopaiból, hol x az oszlop adattípusa. Valójában adatbázis oszlopneveket adunk meg a getX () mód:

while (rs.next ()) {String name = rs.getString ("név"); Egész empId = rs.getInt ("emp_id"); Dupla fizetés = rs.getDouble ("fizetés"); Karaktersorozat = rs.getString ("pozíció"); } 

Hasonlóképpen, az oszlop indexszáma használható a getX () mód az oszlop neve helyett. Az indexszám az SQL select utasítás oszlopainak sorrendje.

Ha a select utasítás nem sorolja fel az oszlopok nevét, akkor az index száma a táblázat oszlopainak sorrendje. Az oszlopindex számozása egyből indul:

Egész empId = rs.getInt (1); Karakterlánc neve = rs.getString (2); Karaktersorozat = rs.getString (3); Dupla fizetés = rs.getDupla (4); 

3. A MetaData lekérése a ResultSet

Ebben a szakaszban megtudhatjuk, hogyan szerezhetünk információkat az oszlop tulajdonságairól és típusairól ResultSet.

Először használjuk a getMetaData () módszer a mi ResultSet a ResultSetMetaData:

ResultSetMetaData metaData = rs.getMetaData ();

Ezután kapjuk meg az oszlopok számát ResultSet:

Egész szám oszlopCount = metaData.getColumnCount ();

Továbbá az alábbi módszerek bármelyikét felhasználhatjuk metaadat-objektumunkon az egyes oszlopok tulajdonságainak lekéréséhez:

  • getColumnName (int oszlopszám) hogy megkapja az oszlop nevét
  • getColumnLabel (int columnNumber) az oszlop címkéjének eléréséhez, amelyet után adunk meg MINT az SQL lekérdezésben
  • getTableName (int oszlopNumber) hogy megkapjuk a táblázat nevét, amelyhez ez az oszlop tartozik
  • getColumnClassName (int oszlopszám) az oszlop Java adattípusának megszerzéséhez
  • getColumnTypeName (int oszlopszám) hogy megkapja az oszlop adattípusát az adatbázisban
  • getColumnType (int columnNumber) hogy megkapja az oszlop SQL adattípusát
  • isAutoIncrement (int columnNumber) azt jelzi, hogy az oszlop automatikus növekmény-e
  • isCaseSensitive (int oszlopNumber) meghatározza, hogy az oszlop eset számít-e
  • isSearchable (int oszlopNumber) azt javasolja, hogy használhatjuk-e az oszlopot a hol az SQL lekérdezés záradéka
  • isCurrency (int oszlopNumber) jelzi, ha az oszlop készpénzértéket tartalmaz
  • isNullable (int oszlopNumber) visszatér nulla ha az oszlop nem lehet null, egy ha az oszlop tartalmazhat null értéket, és kettő ha az oszlop semmissége nem ismert
  • isSigned (int oszlopNumber) visszatér igaz ha az oszlop értékei alá vannak írva, különben visszatér hamis

Iteráljunk végig az oszlopokon, hogy megkapjuk tulajdonságait:

for (int columnNumber = 1; columnNumber <= columnCount; columnNumber ++) {String catalogName = metaData.getCatalogName (columnNumber); String className = metaData.getColumnClassName (oszlopszám); Karakterlánc = metaData.getColumnLabel (columnNumber); Karakterlánc neve = metaData.getColumnName (columnNumber); String typeName = metaData.getColumnTypeName (oszlopszám); int típus = metaData.getColumnType (oszlopNumber); String tableName = metaData.getTableName (oszlopszám); String schemaName = metaData.getSchemaName (oszlopszám); logikai isAutoIncrement = metaData.isAutoIncrement (oszlopNumber); logikai isCaseSensitive = metaData.isCaseSensitive (oszlopNumber); logikai isCurrency = metaData.isCurrency (columnNumber); logikai isDefiniteWritable = metaData.isDefinitelyWritable (oszlopNumber); logikai isReadOnly = metaData.isReadOnly (oszlopNumber); logikai isSearchable = metaData.isSearchable (columnNumber); logikai isReadable = metaData.isReadOnly (oszlopNumber); logikai isSigned = metaData.isSigned (oszlopNumber); logikai isWritable = metaData.isWritable (oszlopNumber); int nullable = metaData.isNullable (oszlopNumber); }

4. Navigálás a ResultSet

Amikor megszerezzük a ResultSet, a kurzor helyzete az első sor előtt van. Sőt, alapértelmezés szerint a ResultSet csak előre halad. De használhatunk egy görgethetőt ResultSet egyéb navigációs opciókhoz.

Ebben a részben a különféle navigációs lehetőségeket tárgyaljuk.

4.1. ResultSet Típusok

ResultSet típusa azt jelzi, hogy miként fogjuk átirányítani az adatkészletet:

  • TYPE_FORWARD_ONLY - az alapértelmezett opció, amelyben a kurzor az elejétől a végéig mozog
  • TYPE_SCROLL_INSENSITIVE - kurzorunk előre és hátra egyaránt mozoghat az adatkészleten; ha az adatkészleten történő mozgás közben az alapul szolgáló adatok változnak, azokat figyelmen kívül hagyják; az adatkészlet az adatokat tartalmazza, amikor az adatbázis lekérdezése visszaadja az eredményt
  • TYPE_SCROLL_SENSITIVE - hasonlóan a görgetés érzéketlen típushoz, azonban ennél a típusnál az adatkészlet azonnal tükrözi az alapul szolgáló adatok bármilyen változását

Nem minden adatbázis támogatja az összes ResultSet típusok. Tehát ellenőrizzük, hogy a típus támogatott-e a supportResultSetType miénken DatabaseMetaData tárgy:

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

4.2. Görgethető ResultSet

Hogy görgethető legyen ResultSet, meg kell adja át néhány további paramétert a Nyilatkozat.

Például kapnánk egy görgethetőt ResultSet bármelyik használatával TYPE_SCROLL_INSENSITIVE vagy TYPE_SCROLL_SENSITIVE mint a ResultSet típus:

PreparedStatement pstmt = dbConnection.prepareStatement ("válasszon * az alkalmazottak közül", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery (); 

4.3. Navigációs beállítások

Az alábbi lehetőségek bármelyikét használhatjuk görgethető módon ResultSet:

  • következő() - az aktuális pozícióból a következő sorra halad
  • előző() - áthalad az előző sorra
  • első() - a. első sorához navigál ResultSet
  • utolsó() - az utolsó sorra ugrik
  • beforeFirst () - elindul a kezdésig; hívás következő() miénken ResultSet miután meghívta ezt a módszert, visszatér az első sor a mi ResultSet
  • afterLast () - a végére ugrik; hívás előző () a ResultSet-en a módszer végrehajtása után visszatér az utolsó sor a ResultSet
  • relatív (int numOfRows) - előre vagy hátra az aktuális helyzetből a numOfRows
  • abszolút (int sorszám) - ugrik a rowNumber meghatározott

Lássunk néhány példát:

PreparedStatement pstmt = dbConnection.prepareStatement ("válasszon * az alkalmazottak közül", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery (); while (rs.next ()) {// az eredmények elsőtől az utolsóig történő ismétlése} rs.beforeFirst (); // ugrik vissza a kezdőpontra, az első sor előtt rs.afterLast (); // az eredménysor végére ugrik rs.first (); // navigál az első sorra rs.last (); // az utolsó sorra megy. abszolút (2); // ugrik a 2. sorra rs.relative (-1); // ugrik az előző sorra rs.relative (2); // két sorral előreugrik, míg (rs.previous ()) {// az aktuális sorról az első sorra visszafelé ismétlik} 

4.4. ResultSet Sorszám

Használjuk getRow () hogy megkapjuk az aktuális sorszámunkat ResultSet.

Először a ResultSet majd használd getRow () a rekordok számának megszerzéséhez:

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

5. Adatok frissítése a ResultSet

Alapértelmezés szerint a ResultSet csak olvasható. Használhatunk azonban egy frissíthető fájlt ResultSet a sorok beszúrásához, frissítéséhez és törléséhez.

5.1. ResultSet Egyidejűség

A párhuzamossági mód jelzi, ha a ResultSet frissíteni tudja az adatokat.

A CONCUR_READ_ONLY opció az alapértelmezett, és akkor kell használni, ha nem kell frissítenünk az adatokat a ResultSet.

Ha azonban frissítenünk kell az adatokat a ResultSet, aztán a CONCUR_UPDATABLE opciót kell használni.

Nem minden adatbázis támogatja az összes egyidejűségi módot ResultSet típusok. Ezért ellenőriznünk kell, hogy a kívánt típusú és egyidejűségi mód támogatott-e a supportResultSetConcurrency () módszer:

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

5.2. Frissíthető fájl beszerzése ResultSet

Frissíthető fájl megszerzéséhez ResultSet, további paramétert kell átadnunk a Nyilatkozat. Ehhez használjuk CONCUR_UPDATABLE harmadik paraméterként egy utasítás létrehozása közben:

PreparedStatement pstmt = dbConnection.prepareStatement ("válasszon * az alkalmazottak közül", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery ();

5.3. Sor frissítése

Ebben a szakaszban egy sort frissítünk a frissíthető segítségével ResultSet az előző szakaszban létrehozott.

Hívással sorban frissíthetjük az adatokat updateX () metódusok, az oszlopnevek és értékek átadása a frissítéshez. Bármely támogatott adattípust használhatunk a x ban,-ben updateX () módszer.

Frissítsük a "fizetés" oszlop, amely típusú kettős:

rs.updateDouble ("fizetés", 1100,0);

Vegye figyelembe, hogy ez csak frissíti az adatokat a ResultSet, de a módosításokat még nem menti vissza az adatbázis.

Végül hívjuk updateRow () nak nek mentse a frissítéseket az adatbázisba:

rs.updateRow (); 

Az oszlopnevek helyett átadhatjuk az oszlopindexet a updateX () mód. Ez hasonló az oszlopindex használatához az értékek használatához getX () mód. Az oszlop nevének vagy indexének továbbítása a updateX () módszerek ugyanazt az eredményt adják:

rs.updateDouble (4, 1100,0); rs.updateRow (); 

5.4. Sor beszúrása

Most illesszünk be egy új sort a frissíthető fájlunkkal ResultSet.

Először is használni fogjuk moveToInsertRow () a kurzor mozgatásához új sor beszúrása:

rs.moveToInsertRow ();

Ezután hívnunk kell updateX () módszerek az információ hozzáadásához a sorhoz. Adatot kell szolgáltatnunk az adatbázis-táblázat összes oszlopának. Ha nem adunk meg adatokat minden oszlopnak, akkor az alapértelmezett oszlopértéket használjuk:

rs.updateString ("név", "Venkat"); rs.updateString ("pozíció", "DBA"); rs.updateDouble ("fizetés", 925,0);

Akkor hívjuk insertRow () új sor beszúrásához az adatbázisba:

rs.insertRow ();

Végül használjuk moveToCurrentRow (). Ez visszaviszi a kurzor pozícióját arra a sorra, amelyen voltunk, mielőtt új sor beszúrását kezdtük volna a moveToInsertRow () módszer:

rs.moveToCurrentRow ();

5.5. Sor törlése

Ebben a szakaszban törölni fogunk egy sort a frissíthető szolgáltatásunkkal ResultSet.

Először navigálunk a törölni kívánt sorra. Aztán felhívjuk a deleteRow () módszer az aktuális sor törlésére:

rs abszolút (2); rs.deleteRow ();

6. Tarthatóság

A tarthatóság határozza meg, hogy a mi ResultSet adatbázis-tranzakció végén lesz nyitva vagy zárva.

6.1. Tarthatósági típusok

Használat CLOSE_CURSORS_AT_COMMIT ha a ResultSet nem szükséges a tranzakció végrehajtása után.

Használat HOLD_CURSORS_OVER_COMMIT hogy tarthatót hozzon létre ResultSet. Egy tartható ResultSet az adatbázis-tranzakció végrehajtása után sem záródik le.

Nem minden adatbázis támogatja az összes tartási típust.

Tehát, nézzük ellenőrizze, hogy a tarthatóság típusa támogatott-e felhasználásával supportResultSetHoldability () miénken DatabaseMetaData tárgy. Ezután megkapjuk az adatbázis alapértelmezett tárolhatóságát getResultSetHoldability ():

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

6.2. Tartható ResultSet

Tartható létrehozásához ResultSet, meg kell adnunk a tarthatóság írja be utolsó paraméterként az a létrehozása közben Nyilatkozat. Ezt a paramétert a párhuzamossági mód után adják meg.

Vegye figyelembe, hogy ha Microsoft SQL Server-t (MSSQL) használunk, akkor az adatbázis-kapcsolaton kell megadnunk a tarthatóságot, nem pedig a ResultSet:

dbConnection.setHoldability (ResultSet.HOLD_CURSORS_OVER_COMMIT);

Lássuk ezt működés közben. Először hozzunk létre egy Nyilatkozat, beállítva a tarthatóságot HOLD_CURSORS_OVER_COMMIT:

Utasítás pstmt = dbConnection.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT)

Most frissítsünk egy sort, miközben lekérjük az adatokat. Ez hasonló a korábban tárgyalt frissítési példához, azzal a különbséggel, hogy folytatjuk az iterációt a ResultSet miután elvégezte a frissítési tranzakciót az adatbázisban. Ez jól működik a MySQL és az MSSQL adatbázisokban is:

dbConnection.setAutoCommit (hamis); ResultSet rs = pstmt.executeQuery ("válasszon * az alkalmazottak közül"); while (rs.next ()) {if (rs.getString ("név"). equalsIgnoreCase ("john")) {rs.updateString ("név", "John Doe"); rs.updateRow (); dbConnection.commit (); }} rs.last (); 

Érdemes megjegyezni, hogy a MySQL csak támogat HOLD_CURSORS_OVER_COMMIT. Tehát, még akkor is, ha használjuk CLOSE_CURSORS_AT_COMMIT, figyelmen kívül hagyja.

Az MSSQL adatbázis támogatja CLOSE_CURSORS_AT_COMMIT. Ez azt jelenti, hogy a ResultSet amikor a tranzakciót elkövetjük. Ennek eredményeként a ResultSet a tranzakció elkövetése után a „Kurzor nem nyitott hiba” eredményt kap. Ezért nem nyerhetünk további rekordokat a ResultSet.

7. Letöltés mérete

Jellemzően, amikor adatokat tölt be a ResultSet, az adatbázis-illesztőprogramok döntenek az adatbázisból beolvasandó sorok számáról. Például egy MySQL adatbázisban a ResultSet általában az összes rekordot egyszerre tölti be a memóriába.

Néha előfordulhat, hogy nagyszámú rekorddal kell megküzdenünk, amelyek nem férnek el a JVM memóriánkban. Ebben az esetben a letöltési méret tulajdonságot bármelyikünkre felhasználhatjuk Nyilatkozat vagy ResultSet tiltakozik az eredetileg visszaküldött rekordok számának korlátozása érdekében.

Ha további eredményekre van szükség, ResultSet lekér egy másik rekordköteget az adatbázisból. A Fetch size tulajdonság használatával megtehetjük javaslatot ad az adatbázis-illesztőprogramnak az adatbázis-utanként beolvasandó sorok számáról. Az általunk megadott lekérési méretet a későbbi adatbázis-utakra alkalmazzuk.

Ha nem adjuk meg a betöltött méretet ResultSet, akkor a Nyilatkozat használt. Ha egyiküknél sem adjuk meg a letöltés méretét Nyilatkozat vagy a ResultSet, akkor az adatbázis alapértelmezett értékét használjuk.

7.1. A Fetch Size használata a Nyilatkozat

Most nézzük meg a letöltés méretét Nyilatkozat akcióban. Megadjuk a Nyilatkozat 10 rekordig. Ha lekérdezésünk 100 rekordot ad vissza, akkor 10 adatbázis kerül oda-vissza, és minden alkalommal 10 rekordot tölt be:

PreparedStatement pstmt = dbConnection.prepareStatement ("válasszon * az alkalmazottak közül", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); pstmt.setFetchSize (10); ResultSet rs = pstmt.executeQuery (); míg (rs.next ()) {// iterál az eredményhalmazon keresztül}

7.2. A Fetch Size használata a ResultSet

Változtassuk meg az előző példánk betöltött méretét a ResultSet.

Először a lekérés méretét fogjuk használni Nyilatkozat. Ez lehetővé teszi a mi ResultSet hogy a lekérdezés végrehajtása után kezdetben 10 rekordot töltsön be.

Ezután módosítjuk a letöltési méretet a ResultSet. Ez felülírja azt a lekérési méretet, amelyet korábban megadott a Nyilatkozat. Tehát az összes következő utazás 20 rekordot tölt be, amíg az összes rekord betöltődik.

Ennek eredményeként csak 6 adatbázis-utazás lesz az összes rekord betöltésére:

PreparedStatement pstmt = dbConnection.prepareStatement ("válasszon * az alkalmazottak közül", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); pstmt.setFetchSize (10); ResultSet rs = pstmt.executeQuery (); rs.setFetchSize (20); míg (rs.next ()) {// iterál az eredményhalmazon keresztül}

Végül meglátjuk, hogyan lehet módosítani a ResultSet miközben iterálta az eredményeket.

Az előző példához hasonlóan először a lekérés méretét állítjuk be 10-re Nyilatkozat. Tehát az első 3 adatbázis-utunk 10 rekordot tölt be utanként.

És akkor módosítjuk a lekérés méretét ResultSet 20-ra, miközben elolvassa a 30. lemezt. Tehát a következő 4 utazásonként 20 rekordot tölt be utanként.

Ezért mind a 100 rekord betöltéséhez 7 adatbázis-utazásra lesz szükségünk:

PreparedStatement pstmt = dbConnection.prepareStatement ("válasszon * az alkalmazottak közül", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); pstmt.setFetchSize (10); ResultSet rs = pstmt.executeQuery (); int sorSzám = 0; while (rs.next ()) {// iterál az eredményhalmazon, ha (rowCount == 30) {rs.setFetchSize (20); } rowCount ++; }

8. Következtetés

Ebben a cikkben láttuk, hogyan kell használni a ResultSet API adatok lekéréséhez és frissítéséhez egy adatbázisból. Az általunk tárgyalt speciális funkciók közül több az általunk használt adatbázistól függ. Így használat előtt ellenőriznünk kell a funkciók támogatását.

Mint mindig, a kód elérhető a GitHubon.