Bevezetés a JDBC-be
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 FOLYAMATOT1. Á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ó