Bevezetés a JDBC-be

Java Top

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

1. Áttekintés

Ebben a cikkben megnézzük a JDBC-t (Java Database Connectivity), amely API egy lekérdezések összekapcsolásához és végrehajtásához az adatbázisban.

A JDBC bármilyen adatbázissal képes működni, amennyiben megfelelő illesztőprogramok vannak megadva.

2. JDBC illesztőprogramok

A JDBC illesztőprogram egy JDBC API megvalósítás, amelyet egy adott típusú adatbázishoz való csatlakozáshoz használnak. A JDBC illesztőprogramoknak több típusa van:

  • 1. típus - hozzárendelést tartalmaz egy másik adatelérési API-hoz; erre példa a JDBC-ODBC illesztőprogram
  • 2. típus - olyan megvalósítás, amely a cél adatbázis kliens oldali könyvtárait használja; natív API illesztőprogramnak is nevezik
  • 3. típus - köztes szoftver segítségével konvertálja a JDBC hívásokat adatbázis-specifikus hívásokká; más néven hálózati protokoll-illesztőprogram
  • 4. típus - közvetlenül csatlakozzon egy adatbázishoz a JDBC hívások adatbázis-specifikus hívássá alakításával; adatbázis protokoll illesztőprogramok vagy vékony illesztőprogramok,

A leggyakrabban használt típus a 4. típus, mivel annak az előnye, hogy létezik platformfüggetlen. Közvetlen kapcsolat az adatbázis-kiszolgálóval jobb teljesítményt nyújt más típusokhoz képest. Az ilyen típusú illesztőprogramok hátránya, hogy adatbázis-specifikusak - mivel minden adatbázisnak megvan a saját protokollja.

3. Csatlakozás egy adatbázishoz

Az adatbázishoz való csatlakozáshoz egyszerűen inicializálnunk kell az illesztőprogramot, és meg kell nyitnunk egy adatbázis-kapcsolatot.

3.1. Az illesztőprogram regisztrálása

Példánkhoz egy 4-es típusú adatbázis-protokoll illesztőprogramot fogunk használni.

Mivel MySQL adatbázist használunk, szükségünk van a mysql-connector-java függőség:

 mysql mysql-connector-java 6.0.6 

Ezután regisztráljuk az illesztőprogramot a Class.forName () módszer, amely dinamikusan tölti be a vezetőosztályt:

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

A JDBC régebbi verzióiban a kapcsolat megszerzése előtt először inicializálnunk kellett a JDBC illesztőprogramot a Class.forName módszer. A JDBC 4.0-tól kezdődően az osztálypályán található összes illesztőprogram automatikusan betöltődik. Ezért erre nincs szükségünk Osztály.Név része a modern környezetben.

3.2. A kapcsolat létrehozása

A kapcsolat megnyitásához használhatjuk a getConnection () a metódusa DriverManager osztály. Ehhez a módszerhez kapcsolat URL-re van szükség Húr paraméter:

próbálkozzon (Connection con = DriverManager .getConnection ("jdbc: mysql: // localhost: 3306 / myDb", "user1", "pass")) {// használja a con itt}

Mivel a Kapcsolat egy Automatikusan zárható erőforrás, akkor azt a erőforrásokkal próbálkozzon Blokk.

A kapcsolat URL szintaxisa a használt adatbázis típusától függ. Nézzünk meg néhány példát:

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

Csatlakozás a megadotthoz myDb adatbázis létrehozásához létre kell hoznunk az adatbázist és a felhasználót, és hozzá kell adnunk a szükséges hozzáférést:

CREATE DATABASE myDb; CREATE USER 'user1' FELHASZNÁLÓJA „pass” -AL; GRANT MINDEN a myDb-n. * A 'user1' címre;

4. SQL utasítások végrehajtása

Az SQL utasítások elküldése az adatbázisba használhatunk típusú példányokat Nyilatkozat, PreparedStatement, vagy CallableStatement, amelyet a Kapcsolat tárgy.

4.1. Nyilatkozat

A Nyilatkozat interfész tartalmazza az SQL parancsok végrehajtásához szükséges alapvető funkciókat.

Először hozzunk létre egy Nyilatkozat tárgy:

próbáld ki (Statm stmt = con.createStatement ()) {// itt használd az stmt-t}

Ismét együtt kellene működnünk Nyilatkozats belül a erőforrásokkal próbálkozzon blokk az automatikus erőforrás-kezeléshez.

Mindenesetre az SQL utasítások végrehajtása három módszer segítségével történhet:

  • executeQuery () a SELECT utasításokhoz
  • executeUpdate () az adatok vagy az adatbázis-struktúra frissítéséhez
  • végrehajtani () mindkét fenti esetben használható, ha az eredmény ismeretlen

Használjuk a végrehajtani () módszer a diákok táblázat az adatbázisunkba:

String tableSql = "Táblázat létrehozása, ha nem léteznek alkalmazottak" + "(emp_id int ELSŐ KULCS AUTO_INCREMENT, név varchar (30)," + "pozíció varchar (30), fizetés duplája)"; stmt.execute (tableSql);

A végrehajtani () módszer az adatok frissítésére, majd a stmt.getUpdateCount () A metódus az érintett sorok számát adja vissza.

Ha az eredmény 0, akkor vagy egy sor sem érintett, vagy adatbázis-struktúra frissítési parancs volt.

Ha az érték -1, akkor a parancs egy SELECT lekérdezés volt; azután az eredményt megszerezhetjük stmt.getResultSet ().

Ezután adjunk hozzá egy rekordot a táblázatunkhoz a executeUpdate () módszer:

String insertSql = "INSERT INTO alkalmazottak (név, beosztás, fizetés)" + "ÉRTÉKEK ('john', 'fejlesztő', 2000)"; stmt.executeUpdate (insertSql);

A metódus visszaadja a sorokat frissítő parancs érintett sorainak számát, vagy az adatbázis struktúráját frissítő parancsok 0-át.

A rekordok lekérhetők a táblázatból a executeQuery () metódus, amely egy típusú objektumot ad vissza ResultSet:

Karakterlánc selectSql = "SELECT * FROM alkalmazottaktól"; próbálkozzon (ResultSet resultSet = stmt.executeQuery (selectSql)) {// használja a resultSet itt}

Gondoskodnunk kell a bezárásáról ResultSet használat után. Ellenkező esetben az alapul szolgáló kurzort a vártnál jóval hosszabb ideig tarthatjuk nyitva. Ehhez ajánlott a erőforrásokkal próbálkozzon blokkolja, mint a fenti példánkban.

4.2. PreparedStatement

PreparedStatement az objektumok előre lefordított SQL szekvenciákat tartalmaznak. Egy vagy több paraméterük lehet kérdőjellel jelölve.

Hozzunk létre egy PreparedStatement amely frissíti a rekordokat a alkalmazottak táblázat a megadott paraméterek alapján:

Karaktersorozat updatePositionSql = "A dolgozók frissítése SET pozíció =? WHERE emp_id =?"; próbáld (PreparedStatement pstmt = con.prepareStatement (updatePositionSql)) {// itt használd a pstmt-t}

Paraméterek hozzáadása a PreparedStatement, használhatunk egyszerű szetteket - setX () - ahol X a paraméter típusa, és a metódus argumentumok a paraméter sorrendje és értéke:

pstmt.setString (1, "vezető fejlesztő"); pstmt.setInt (2, 1);

Az utasítás a fent leírt három módszer egyikével hajtódik végre: executeQuery (), executeUpdate (), execute () SQL nélkül Húr paraméter:

int rowsAffected = pstmt.executeUpdate ();

4.3. CallableStatement

A CallableStatement interfész lehetővé teszi a tárolt eljárások hívását.

A CallableStatement objektumot használhatjuk PreparCall () a metódusa Kapcsolat:

Karakterlánc előkészítveSql = "{call insertEmployee (?,?,?,?)}"; próbáld (CallableStatement cstmt = con.prepareCall (PreparSql)) {// itt használd a cstmt-t}

A tárolt eljárás bemeneti paramétereinek beállítása a PreparedStatement interfész, a setX () mód:

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

Ha a tárolt eljárásnak vannak kimeneti paraméterei, akkor azokat hozzá kell adnunk a registerOutParameter () módszer:

cstmt.registerOutParameter (1, Types.INTEGER);

Ezután hajtsuk végre az utasítást, és egy megfelelő segítségével keressük meg a visszaadott értéket getX () módszer:

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

Például a működéshez létre kell hoznunk a tárolt eljárást a MySql adatbázisunkban:

elválasztó // ELJÁRÁS LÉTREHOZ beillesztésMunkavállaló (OUT emp_id int, IN emp_name varchar (30), IN position varchar (30), IN fizetési dupla) BEGIN INSERT INTO alkalmazottak (név, beosztás, bér) ÉRTÉKEK (emp_name, beosztás, fizetés); SET emp_id = LAST_INSERT_ID (); END // határoló;

A insertEmployee A fenti eljárás új rekordot illeszt be a alkalmazottak táblázat a megadott paraméterek felhasználásával és adja vissza az új rekord azonosítóját a emp_id out paraméter.

Ahhoz, hogy egy tárolt eljárást futtathasson a Java-ból, a kapcsolat felhasználójának hozzáféréssel kell rendelkeznie a tárolt eljárás metaadataira. Ez úgy érhető el, hogy a felhasználóknak minden adatbázisban tárolt eljárásra jogot adunk:

TÁMOGAT MINDEN A mysql.proc -on A 'user1' -nek;

Alternatív megoldásként meg tudjuk nyitni a kapcsolatot az ingatlannal noAccessToProcedureBodies állítva igaz:

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

Ez tájékoztatja a JDBC API-t arról, hogy a felhasználónak nincs joga elolvasni az eljárás metaadatait, így az összes paramétert INOUT néven hozza létre. Húr paraméterek.

5. A lekérdezés eredményeinek elemzése

A lekérdezés végrehajtása után az eredményt a jel képviseli ResultSet objektum, amelynek szerkezete hasonló a táblához, vonalakkal és oszlopokkal.

5.1. ResultSet Felület

A ResultSet használja a következő() módszer a következő sorra lépéshez.

Először hozzunk létre egy Munkavállaló osztály letöltött rekordjaink tárolására:

public class Alkalmazott {private int id; privát karakterlánc neve; privát húr pozíció; magán kettős fizetés; // szabványos kivitelező, mérőeszközök, beállítók}

Ezután haladjuk át a ResultSet és hozzon létre egy Munkavállaló objektum minden rekordnál:

Karakterlánc selectSql = "SELECT * FROM alkalmazottaktól"; try (ResultSet resultSet = stmt.executeQuery (selectSql)) {Alkalmazók listája = new ArrayList (); while (resultSet.next ()) {Employee emp = new Employee (); emp.setId (resultSet.getInt ("emp_id")); emp.setName (resultSet.getString ("név")); emp.setPosition (resultSet.getString ("pozíció")); emp.setSalary (resultSet.getDouble ("fizetés")); alkalmazottak.add (emp); }}

Az egyes táblázatcellák értékének lekérése típusú módszerekkel történhet getX (), ahol X a cellaadat típusát jelenti.

A getX () módszerek használhatók egy int a cella sorrendjét képviselő paraméter, vagy a Húr az oszlop nevét képviselő paraméter. Ez utóbbi lehetőség előnyösebb abban az esetben, ha megváltoztatjuk a lekérdezés oszlopainak sorrendjét.

5.2. Frissíthető ResultSet

Implicit módon a ResultSet az objektum csak előre haladhat, és nem módosítható.

Ha használni akarjuk a ResultSet az adatok frissítéséhez és mindkét irányban való áthaladásához létre kell hoznunk a Nyilatkozat objektum további paraméterekkel:

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

Az ilyen típusú navigáláshoz ResultSet, használhatjuk a módszerek egyikét:

  • first (), last (), beforeFirst (), beforeLast () - az a. Első vagy utolsó sorára lépés ResultSet vagy az ezek előtti vonalra
  • következő (), előző () - előre és hátra történő navigáláshoz a ResultSet
  • getRow () - az aktuális sorszám megszerzéséhez
  • moveToInsertRow (), moveToCurrentRow () - új üres sorra ugrás a beszúráshoz, és visszalépés az aktuálisra, ha új sorban van
  • abszolút (int sor) - hogy a megadott sorra lépjen
  • rokon (int nrRows) - a kurzor mozgatásához a megadott számú sort

A. Frissítése ResultSet formátumú módszerekkel végezhető el updateX () ahol X a cellaadat típusa. Ezek a módszerek csak a ResultSet objektum és nem az adatbázis táblák.

Hogy kitartson a ResultSet az adatbázis módosítása, tovább kell használnunk a módszerek egyikét:

  • updateRow () - az adatbázis aktuális sorának változásainak fenntartása
  • insertRow (), deleteRow () - új sor hozzáadása vagy a jelenlegi törlése az adatbázisból
  • refreshRow () - a ResultSet az adatbázis bármilyen változásával
  • cancelRowUpdates () - az aktuális sorban végrehajtott változtatások törlése

Nézzünk meg egy példát ezen módszerek némelyikének használatára az adatok frissítésével a alkalmazottja asztal:

próbálkozz (Statement updatableStmt = con.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE)) {try (ResultSet updatableResultSet = updatableStmt.executeQuery (selectSql)) (updatableRowRo updatableResultSet.updateString ("név", "jelölés"); updatableResultSet.updateString ("pozíció", "elemző"); updatableResultSet.updateDouble ("fizetés", 2000); updatableResultSet.insertRow (); }}

6. A metaadatok elemzése

A JDBC API lehetővé teszi az adatbázisról, metaadatoknak nevezett információk megkeresését.

6.1. DatabaseMetadata

A DatabaseMetadata Az interfész használható általános információk megszerzésére az adatbázisról, például a táblákról, a tárolt eljárásokról vagy az SQL-dialektusról.

Nézzük meg gyorsan, hogyan nyerhetünk információkat az adatbázis táblákból:

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

6.2. ResultSetMetadata

Ez a felület felhasználható információk keresésére egy adott termékkel kapcsolatban ResultSet, például oszlopainak száma és neve:

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. Tranzakciók kezelése

Alapértelmezés szerint minden SQL-utasítás közvetlenül a befejezése után kerül végrehajtásra. Az is lehetséges a tranzakciókat programszerűen ellenőrizni.

Erre akkor lehet szükség, amikor meg akarjuk őrizni az adatok konzisztenciáját, például amikor csak akkor akarunk tranzakciót végrehajtani, ha egy előző sikeresen befejeződött.

Először be kell állítanunk a autoCommit tulajdona Kapcsolat nak nek hamis, majd használja a elkövetni() és visszagörgetés () módszerek a tranzakció ellenőrzésére.

Adjunk hozzá egy második frissítési utasítást a fizetés oszlop az alkalmazott után pozíció oszlopfrissítést, és csomagolja be mindkettőt egy tranzakcióba. Így a fizetést csak akkor frissítik, ha a pozíció sikeresen frissült:

Karakterlánc updatePositionSql = "A dolgozók frissítése BEÁLLÍTÁS =? WHERE emp_id =?"; PreparedStatement pstmt = con.prepareStatement (updatePositionSql); pstmt.setString (1, "vezető fejlesztő"); pstmt.setInt (2, 1); Karaktersorozat updateSalarySql = "FELADAT FEJLESZTÉSE az alkalmazottak fizetését =? WHERE emp_id =?"; PreparedStatement pstmt2 = con.prepareStatement (updateSalarySql); pstmt.setDouble (1, 3000); pstmt.setInt (2, 1); logikai autoCommit = con.getAutoCommit (); próbáld ki a {con.setAutoCommit (hamis); pstmt.executeUpdate (); pstmt2.executeUpdate (); con.commit (); } catch (SQLException exc) {con.rollback (); } végül {con.setAutoCommit (autoCommit); }

A rövidség kedvéért kihagyjuk a erőforrásokkal próbálkozzon blokkolja itt.

8. Az erőforrások bezárása

Amikor már nem használjuk, le kell zárnunk a kapcsolatot az adatbázis-erőforrások felszabadításához.

Ezt megtehetjük a Bezárás() API:

con.close ();

Ha azonban az erőforrást a erőforrásokkal próbálkozzon blokkolni, nem kell hívnunk a Bezárás() módszer kifejezetten, mivel a erőforrásokkal próbálkozzon blokk ezt automatikusan elvégzi helyettünk.

Ugyanez igaz a Nyilatkozats, PreparedStatements, CallableStatements és ResultSets.

9. Következtetés

Ebben az oktatóanyagban áttekintettük a JDBC API-val való munka alapjait.

Mint mindig, a példák teljes forráskódja megtalálható a GitHub oldalon.

Java alsó

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

$config[zx-auto] not found$config[zx-overlay] not found