{"id":434,"date":"2025-02-16T00:25:43","date_gmt":"2025-02-15T22:25:43","guid":{"rendered":"https:\/\/eugo.ro\/?p=434"},"modified":"2025-06-05T22:22:18","modified_gmt":"2025-06-05T19:22:18","slug":"lucrul-cu-baze-de-date","status":"publish","type":"post","link":"https:\/\/eugo.ro\/?p=434","title":{"rendered":"Lucrul cu baze de date"},"content":{"rendered":"<p>&nbsp;<br \/>\nAplica\u0163iile care folosesc baze de date sunt, in general, aplica\u0163ii complexe folosite pentru gestionarea unor informa\u0163ii de dimensiuni mari intr-o manier\u0103 sigur\u0103 \u015fi eficient\u0103.<br \/>\n&nbsp;<br \/>\n<strong>Ce este o baz\u0103 de date ?<\/strong><br \/>\nLa nivelul cel mai general, o baz\u0103 de date reprezint\u0103 o modalitate de stocare a unor informa\u0163ii (date) pe un suport extern, cu posibilitatea reg\u0103sirii acestora.<br \/>\nUzual, o baz\u0103 de date este memorat\u0103 intr-unul sau mai multe fi\u015fiere. Modelul clasic de baze de date este cel rela\u0163ional, in care datele sunt memorate in tabele. Un tabel reprezint\u0103 o structur\u0103 de date format\u0103 dintr-o mul\u0163ime de articole, fiecare articol av\u00e2nd definite o serie de atribute &#8211; aceste atribute corespund coloanelor tabelului, in timp ce o linie va reprezenta un articol. Pe langa tabele, o baz\u0103 de date mai poate con\u0163ine: proceduri \u015fi func\u0163ii, utilizatori \u015fi grupuri de utilizatori, tipuri de date, obiecte, etc.<br \/>\nDintre produc\u0103torii cei mai importan\u0163i de baze de date amintim companiile Oracle, Sybase, IBM, Informix, Microsoft, etc. fiecare furniz\u00e2nd o serie intreag\u0103 de produse \u015fi utilitare pentru lucrul cu baze de date. Aceste produse sunt in general referite prin termenii DBMS (Database Management System) sau, in traducere, SGBD (Sistem de Gestiune a Bazelor de Date). In acest articol vom analiza lucrul cu baze de date din perspectiva program\u0103rii in limbajul Java, f\u0103r\u0103 a descrie particularit\u0103\u0163i ale unei solu\u0163ii de stocare a datelor anume. Vom vedea c\u0103, folosind Java, putem crea aplica\u0163ii care s\u0103 ruleze f\u0103r\u0103 nici o modificare folosind diverse tipuri de baze care au aceea\u015fi structur\u0103, duc\u00e2nd \u0131\u0302n felul acesta no\u0163iunea de portabilitate \u015fi mai departe.<br \/>\n&nbsp;<br \/>\n<strong>Crearea unei baze de date<\/strong><br \/>\nCrearea unei baze de date se face uzual folosind aplica\u0163ii specializate oferite de produc\u0103torul tipului respectiv de sistem de gestiune a datelor, dar exist\u0103 \u015fi posibilitatea de a crea o baza folosind un script SQL. Acest aspect ne va preocupa \u0131\u0302ns\u0103 mai pu\u0163in, exemplele prezentate presupun\u00e2nd c\u0103 baza a fost creat\u0103 deja \u015fi are o anumit\u0103 structur\u0103 specificat\u0103.<br \/>\n&nbsp;<br \/>\n<strong>Accesul la baza de date<\/strong><br \/>\nSe face prin intermediul unui driver specific tipului respectiv de SGBD.Acesta este responsabil cu accesul efectiv la datele stocate, fiind legatura dintre aplica\u0163ie \u015fi baza de date.<br \/>\n&nbsp;<br \/>\n<strong>Limbajul SQL<\/strong><br \/>\nSQL (Structured Query Language) reprezint\u0103 un limaj de programare ce permite interogarea \u015fi actualizarea informa\u0163iilor din baze de date rela\u0163ionale. Acesta este standardizat astfel \u0131\u0302nc\u00e2t diverse tipuri de drivere s\u0103 se comporte identic, oferind astfel o modalitate unitar\u0103 de lucru cu baze de date.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/eugo.ro\/Baze-date\/IMG\/1.png\" alt=\"\" \/><br \/>\n&nbsp;<br \/>\n<strong>JDBC<\/strong><br \/>\nJDBC (Java Database Connectivity) este o interfa\u0163\u0103 standard SQL de acces la baze de date. JDBC este constituit\u0103 dintr-un set de clase \u015fi interfe\u0163e scrise in Java, furniz\u00e2nd mecanisme standard pentru proiectan\u0163ii aplica\u0163iilor ce folosesc de baze de date.<br \/>\nFolosind JDBC este usor sa transmitem secven\u0163e SQL catre baze de date rela\u0163ionale. Cu alte cuvinte, nu este necesar s\u0103 scriem un program pentru a accesa o baz\u0103 de date Oracle, alt program pentru a accesa o baz\u0103 de date Sybase \u015fi asa mai departe. Este de ajuns s\u0103 scriem un singur program folosind Sybase \u015fi asa mai departe. Este de ajuns s\u0103 scriem un singur program folosind API-ul JDBC \u015fi acesta va fi capabil s\u0103 comunice cu drivere diferite, trimi\u0163\u00e2nd secven\u0163e SQL c\u0103tre baza de date dorit\u0103. Bine\u0131\u0302n\u0163eles, scriind codul surs\u0103 in\u00a0 Java, ne este asigurat\u0103 portabilitatea programului. Deci, iat\u0103 dou\u0103 motive puternice care fac combina\u0163ia Java &#8211; JDBC demn\u0103 de luat in seam\u0103.<\/p>\n<p>Pachetele care ofer\u0103 suport pentru lucrul cu baze de date sunt <strong>java.sql<\/strong> ce reprezint\u0103 nucleul tehnologiei JDBC \u015fi, preluat de pe platforma <strong>J2EE, javax.sql<\/strong>.<\/p>\n<p>API-ul JDBC ofer\u0103 urm\u0103toarele facilit\u0103\u0163i:<\/p>\n<ul>\n<li>Stabilirea unei conexiuni cu o baz\u0103 de date.<\/li>\n<li>Efectuarea de secven\u0163e SQL.<\/li>\n<li>Prelucrarea rezultatelor ob\u0163inute.<\/li>\n<\/ul>\n<p><strong>Conectarea la o baz\u0103 de date<\/strong><br \/>\nProcesul de conectare la o baz\u0103 de date implic\u0103 efectuarea a dou\u0103 opera\u0163ii:<\/p>\n<ul>\n<li>Inregistrarea unui driver corespunz\u0103tor.<\/li>\n<li>Realizarea unei conexiuni propriu-zise.<\/li>\n<\/ul>\n<p>O conexiune (sesiune) la o baz\u0103 de date reprezint\u0103 un context prin care sunt trimise secven\u0163e SQL \u015fi primite rezultate. Intr-o aplica\u0163ie pot exista simultan mai multe conexiuni la baze de date diferite sau la aceea\u015fi baz\u0103.<\/p>\n<p>Clasele \u015fi interfe\u0163ele responsabile cu realizarea unei conexiuni sunt:<\/p>\n<ul>\n<li><strong>DriverManager<\/strong> &#8211; este clasa ce se ocup\u0103 cu \u0131\u0302nregistrarea driverelor ce vor fi folosite in aplica\u0163ie;<\/li>\n<li><strong>Driver<\/strong> &#8211; interfa\u0163a pe care trebuie s\u0103 o implementeze orice clas\u0103 ce\u00a0 descrie un driver;<\/li>\n<li><strong>DriverPropertyInfo<\/strong> &#8211; prin intermediul acestei clase pot fi specificate diverse propriet\u0103\u0163i ce vor fi folosite la realizarea conexiunilor;<\/li>\n<li><strong>Connection<\/strong> &#8211; descrie obiectele ce modeleaz\u0103 o conexiune propriu-zis\u0103 cu baza de date.<\/li>\n<\/ul>\n<p>&nbsp;<br \/>\n<strong>Inregistrarea unui driver<\/strong><br \/>\nPrimul lucru pe care trebuie s\u0103-l fac\u0103 o aplica\u0163ie \u0131\u0302n procesul de conectare la o baz\u0103 de date este s\u0103 inregistreze la ma\u015fina virtual\u0103 ce ruleaz\u0103 aplica\u0163ia driverul JDBC responsabil cu comunicarea cu respectiva baz\u0103 de date. Acest lucru presupune \u0131\u0302nc\u0103rcarea \u0131\u0302n memorie a clasei ce implementeaz\u0103 driver-ul \u015fi poate fi realizat\u0103 \u0131\u0302n mai multe modalit\u0103\u0163i.<\/p>\n<p>a. Folosirea clasei <strong>DriverManager<\/strong>:<br \/>\n<em>DriverManager.registerDriver(new TipDriver());<\/em><\/p>\n<p>b. Folosirea metodei <strong>Class.forName<\/strong> ce apeleaz\u0103 ClassLoader-ul ma\u015finii virtuale:<br \/>\n<em>Class.forName(&#8220;TipDriver&#8221;);<\/em><br \/>\n<em>Class.forName(&#8220;TipDriver&#8221;).newInstance();<\/em><\/p>\n<p>c. Setarea propriet\u0103\u0163ii sistem <strong>jdbc.drivers<\/strong>, care poate fi realizat\u0103 in dou\u0103 feluri:<br \/>\n\u2013 De la linia de comand\u0103:<br \/>\n<em>java -Djdbc.drivers=TipDriver Aplicatie<\/em><br \/>\n\u2013 Din program:<br \/>\n<em>System.setProperty(&#8220;jdbc.drivers&#8221;, &#8220;TipDriver&#8221;);<\/em><\/p>\n<p>Folosind aceast\u0103 metod\u0103, specificarea mai multor drivere se face separ\u00e2nd numele claselor cu punct \u015fi virgul\u0103.<br \/>\nDac\u0103 sunt inregistrate mai multe drivere, ordinea de preceden\u0163\u0103 in alegerea driverului folosit la crearea unei noi conexiuni este:<\/p>\n<ul>\n<li>Driverele inregistrate folosind proprietatea jdbc.drivers la ini\u0163ializarea\u00a0 ma\u015finii virtuale ce va rula procesul.<\/li>\n<li>Driverele inregistrate dinamic din aplica\u0163ie.<\/li>\n<\/ul>\n<p>&nbsp;<br \/>\n<strong>Specificarea unei baze de date<\/strong><br \/>\nO dat\u0103 ce un driver JDBC a fost inregistrat, acesta poate fi folosit la stabilirea unei conexiuni cu o baz\u0103 de date. Av\u00e2nd in vedere faptul ca pot exista mai multe drivere inc\u0103rcate \u0131\u0302n memorie, trebuie s\u0103 avem posibilitea de a specifica pe l\u00e2ng\u0103 un identificator al bazei de date \u015fi driverul ce trebuie folosit. Aceasta se realizeaz\u0103 prin intermediul unei adrese specifice, numit\u0103 JDBC URL, ce are urm\u0103torul format:<\/p>\n<p style=\"text-align: center;\"><strong>jdbc:sub-protocol:identificator<\/strong><\/p>\n<p>C\u00e2mpul sub-protocol denume\u015fte tipul de driver ce trebuie folosit pentru realizarea conexiunii \u015fi poate fi odbc, oracle, sybase, db2 \u015fi a\u015fa mai departe.<br \/>\nIdentificatorul bazei de date este un indicator specific fiec\u0103rui driver corespunz\u0103tor bazei de date cu care aplica\u0163ia dore\u015fte s\u0103 interac\u0163ioneze. In func\u0163ie de tipul driver-ului acest identificator poate include numele unei ma\u015fini gazd\u0103, un num\u0103r de port, numele unui fi\u015fier sau al unui director, etc., ca in exemplele de mai jos:<\/p>\n<p><em>jdbc:odbc:test<\/em><br \/>\n<em>jdbc:oracle:thin@persistentjava.com:1521:test<\/em><br \/>\n<em>jdbc:sybase:test<\/em><br \/>\n<em>jdbc:db2:test<\/em><\/p>\n<p>Subprotocolul odbc este un caz specical, in sensul c\u0103 permite specificarea in cadrul URL-ului a unor atribute ce vor fi realizate la crearea unei conexiuni. Sintaxa completa subprotocolului odbc este:<\/p>\n<p style=\"text-align: center;\"><strong><em>jdbc:odbc:identificator[;atribut=valoare]*<\/em><\/strong><\/p>\n<p><em>jdbc:odbc:test<\/em><br \/>\n<em>jdbc:odbc:test;CacheSize=20;ExtensionCase=LOWER<\/em><br \/>\n<em>jdbc:odbc:test;UID=duke;PWD=java<\/em><\/p>\n<p>La primirea unui JDBC URL, DriverManager-ul va parcurge lista driverelor inregistrate in memorie, p\u00e2na c\u00e2nd unul dintre ele va recunoa\u015fte URL-ul respectiv. Dac\u0103 nu exista nici unul potrivit, atunci va fi lansata o excep\u0163ie de tipul SQLException, cu mesajul &#8220;no suitable driver&#8221;.<br \/>\n&nbsp;<br \/>\n<strong>Tipuri de drivere<\/strong><\/p>\n<p>Tipurile de drivere existente ce pot fi folosite pentru realizarea unei conexiuni\u00a0 prin intermediul JDBC se \u0131\u0302mpart \u0131\u0302n urm\u0103toarele categorii:<\/p>\n<p><em>Tip 1. JDBC-ODBC Bridge<\/em><\/p>\n<p><img decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/eugo.ro\/Baze-date\/IMG\/2.png\" alt=\"\" \/><\/p>\n<p>Acest tip de driver permite conectarea la o baz\u0103 de date care a fost inregistrat\u0103 \u0131\u0302n prealabil \u0131\u0302n ODBC. ODBC (Open Database Conectivity) reprezint\u0103 o modalitate de a uniformiza accesul la baze de date, asociind acestora un identificator DSN (Data Source Name) \u015fi diver\u015fi parametri necesari conect\u0103rii. Conectarea efectiv\u0103 la baza de date se va face prin intermediul acestui identificator, driver-ul ODBC efectu\u00e2nd comunicarea cu driverul nativ al bazei de date.<br \/>\nDe\u015fi simplu de utilizat, solu\u0163ia JDBC-ODBC nu este portabil\u0103 \u015fi comunicarea cu baza de date sufer\u0103 la nivelul vitezei de execu\u0163ie datorit\u0103 multiplelor redirect\u0103ri \u0131\u0302ntre drivere. De asemenea, at\u00e2t ODBC-ul c\u00e2t \u015fi driver-ul nativ trebuie s\u0103 existe pe ma\u015fina pe care ruleaz\u0103 aplica\u0163ia.<br \/>\nClasa Java care descrie acest tip de driver JDBC este:<\/p>\n<p style=\"text-align: center;\"><strong>sun.jdbc.odbc.JdbcOdbcDriver<\/strong><\/p>\n<p>\u015fi este inclus\u0103 in distribu\u0163ia standard J2SDK. Specificarea bazei de date se face printr-un URL de forma:<\/p>\n<p style=\"text-align: center;\"><strong>jdbc:odbc:identificator<\/strong><\/p>\n<p>unde identificator este profilul (DSN) creat bazei de date \u0131\u0302n ODBC.<\/p>\n<p><em>Tip 2. Driver JDBC &#8211; Driver nativ<\/em><\/p>\n<p><img decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/eugo.ro\/Baze-date\/IMG\/3.png\" alt=\"\" \/><\/p>\n<p>Acest tip de driver transform\u0103 cererile JDBC direct in apeluri c\u0103tre driverul nativ al bazei de date, care trebuie instalat \u0131\u0302n prealabil. Clase Java care implementeaz\u0103 astfel de drivere pot fi procurate de la produc\u0103torii de SGBD-uri, distribu\u0163ia standard J2SDK neincluz\u00e2nd nici unul.<\/p>\n<p><em>Tip 3. Driver JDBC &#8211; Server<\/em><\/p>\n<p><img decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/eugo.ro\/Baze-date\/IMG\/4.png\" alt=\"\" \/> Acest tip de driver transform\u0103 cererile JDBC folosind un protocol de re\u0163ea independent, acestea fiind apoi transormate folosind o aplica\u0163ie server intr-un protocol specfic bazei de date. Introducerea serverului ca nivel intermediar aduce flexibilitate maxim\u0103 \u0131\u0302n sensul c\u0103 vor putea fi realizate conexiuni cu diferite tipuri de baze, f\u0103r\u0103 nici o modificare la nivelul clientului. Protocolul folosit este specific fiec\u0103rui produc\u0103tor.<\/p>\n<p><em>Tip 4. Driver JDBC nativ<\/em><\/p>\n<p><img decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/eugo.ro\/Baze-date\/IMG\/5.png\" alt=\"\" \/>Acest tip de driver transform\u0103 cererile JDBC direct \u0131\u0302n cereri c\u0103tre baza de date folosind protocolul de re\u0163ea al acesteia. Aceast\u0103 solu\u0163ie este cea mai rapid\u0103, fiind preferat\u0103 la dezvoltarea aplica\u0163iilor care manevreaz\u0103 volume mari de date \u015fi viteza de execu\u0163ie este critic\u0103. Drivere de acest tip pot fi procurate de la diver\u015fi produc\u0103tori de SGBD-uri.<br \/>\n&nbsp;<br \/>\n<strong>Realizarea unei conexiuni<\/strong><\/p>\n<p>Metoda folosit\u0103 pentru realizarea unei conexiuni este getConnection din clasa DriverManager \u015fi poate avea mai multe forme:<\/p>\n<p><em>Connection c = DriverManager.getConnection(url);<\/em><br \/>\n<em>Connection c = DriverManager.getConnection(url, username, password);<\/em><br \/>\n<em>Connection c = DriverManager.getConnection(url, dbproperties);<\/em><\/p>\n<p><strong>Stabilirea unei conexiuni folosind driverul JDBC-ODBC<\/strong><\/p>\n<p><em>String url = &#8220;jdbc:odbc:test&#8221; ;<\/em><br \/>\n\/\/ sau <em>url = &#8220;jdbc:odbc:test;UID=duke;PWD=java&#8221; ;<\/em><br \/>\n<em>try {<\/em><br \/>\n<em>Class.forName(&#8220;sun.jdbc.odbc.JdbcOdbcDriver&#8221;);<\/em><br \/>\n<em>} catch(ClassNotFoundException e) {<\/em><br \/>\n<em>System.err.print(&#8220;ClassNotFoundException: &#8221; + e) ;<\/em><br \/>\n<em>return ;<\/em><br \/>\n<em>}<\/em><br \/>\n<em>Connection con ;<\/em><br \/>\n<em>try {<\/em><br \/>\n<em>con = DriverManager.getConnection(url, &#8220;duke&#8221;, &#8220;java&#8221;);<\/em><br \/>\n<em>} catch(SQLException e) {<\/em><br \/>\n<em>System.err.println(&#8220;SQLException: &#8221; + e);<\/em><\/p>\n<p><em>} finally {<\/em><br \/>\n<em>try{<\/em><br \/>\n<em>con.close ;<\/em><br \/>\n<em>} catch(SQLException e) {<\/em><br \/>\n<em>System.err.println(SQLException: &#8221; + e) ;<\/em><br \/>\n<em>\u00a0\u00a0\u00a0\u00a0 }<\/em><br \/>\n<em>}<\/em><br \/>\n&nbsp;<br \/>\n<strong>Stabilirea unei conexiuni folosind un driver MySql<\/strong><\/p>\n<p>Folosirea diferitelor tipuri de drivere implic\u0103 doar schimbarea numelui clasei ce reprezint\u0103 driverul \u015fi a modalit\u0103\u0163ii de specificare a bazei de date.<\/p>\n<p><em>String url = &#8220;jdbc:mysql:\/\/localhost\/test&#8221; ;<\/em><br \/>\n<em>\/\/ sau url = &#8220;jdbc:mysql:\/\/localhost\/test?user=duke&amp;password=java&#8221;;<\/em><br \/>\n<em>try {<\/em><br \/>\n<em>Class.forName(&#8220;com.mysql.jdbc.Driver&#8221;) ;<\/em><br \/>\n<em>} catch(ClassNotFoundException e) {<\/em><br \/>\n<em>&#8230;<\/em><\/p>\n<p>O conexiune va fi folosit\u0103 pentru:<\/p>\n<ul>\n<li>Crearea de secven\u0163e SQL utilizate pentru interogarea sau actualizarea bazei.<\/li>\n<li>Aflarea unor informa\u0163ii legate de baza de date (meta-date).<\/li>\n<\/ul>\n<p>De asemenea, clasa <strong><em>Connection<\/em><\/strong> asigur\u0103 facilit\u0103\u0163i pentru controlul tranzac\u0163iilordin memorie c\u0103tre baza de date prin metodele <em><strong>commit, rollback, setAutoCommit.<\/strong><\/em><br \/>\nInchiderea unei conexiuni se realizeaz\u0103 prin metoda <em><strong>close<\/strong><\/em>.<br \/>\n&nbsp;<br \/>\n<strong>Efectuarea de secven\u0163e SQL<\/strong><\/p>\n<p>O dat\u0103 facut\u0103 conectarea cu metoda <strong><em>DriverManager.getConection<\/em><\/strong>, se poate folosi obiectul <em>Connection<\/em> rezultat pentru a se crea obiecte de tip <em><strong>Statement,PreparedStatement<\/strong><\/em> sau <em><strong>CallableStatement<\/strong><\/em> cu ajutorul c\u0103rora putem trimite secven\u0163e SQL c\u0103tre baza de date. Cele mai uzuale comenzi SQL sunt cele folosite pentru:<\/p>\n<ul>\n<li>Interogarea bazei de date: <strong>SELECT<\/strong><\/li>\n<li>Actualizarea datelor: <strong>INSERT<\/strong>, <strong>UPDATE<\/strong>, <strong>DELETE<\/strong><\/li>\n<li>Actualizarea structurii: <strong>CREATE<\/strong>, <strong>ALTER<\/strong>, <strong>DROP<\/strong> &#8211; acestea mai sunt numite instruc\u0163iuni <em>DDL (Data Definition Language)<\/em><\/li>\n<li>Apelarea unei proceduri stocate: <strong>CALL<\/strong><\/li>\n<\/ul>\n<p>Dup\u0103 cum vom vedea, ob\u0163inerea \u015fi prelucrarea rezultatelor unei interog\u0103ri este realizat\u0103 prin intermediul obiectelor de tip <em><strong>ResultSet<\/strong><\/em>.<br \/>\n&nbsp;<br \/>\n<strong>Interfa\u0163a Statement<\/strong><\/p>\n<p>Interfa\u0163a Statement ofer\u0103 metodele de baz\u0103 pentru trimiterea de secven\u0163e SQL c\u0103tre baza de date \u015fi ob\u0163inerea rezultatelor, celelalte dou\u0103 interfe\u0163e:<br \/>\n<em>PreparedStatement<\/em> \u015fi <em>CallableStatement<\/em> fiind derivate din aceasta.<br \/>\nCrearea unui obiect <em>Statement<\/em> se realizeaz\u0103 prin intermediul metodei <em>createStatement<\/em> a clasei <em>Connection<\/em>, f\u0103r\u0103 nici un argument:<\/p>\n<p><em>Connection con = DriverManager.getConnection(url);<\/em><br \/>\n<em>Statement stmt = con.createStatement();<\/em><\/p>\n<p>Execu\u0163ia unei secven\u0163e SQL poate fi realizat\u0103 prin intermediul a trei metode:<\/p>\n<p><strong>1. executeQuery<\/strong><\/p>\n<p>Este folosit\u0103 pentru realizarea de interog\u0103ri de tip SELECT. Metoda returneaz\u0103un obiect de tip ResultSet ce va con\u0163ine sub o form\u0103 tabelar\u0103 rezultatul interog\u0103rii.<\/p>\n<p><em>String sql = &#8220;SELECT * FROM persoane&#8221;;<\/em><br \/>\n<em>ResultSet rs = stmt.executeQuery(sql);<\/em><\/p>\n<p><strong>2. executeUpdate<\/strong><\/p>\n<p>Este folosit\u0103 pentru actualizarea datelor (<strong>INSERT<\/strong>, <strong>UPDATE<\/strong>, <strong>DELETE<\/strong>) sau a structurii bazei de date (<strong>CREATE<\/strong>, <strong>ALTER<\/strong>, <strong>DROP<\/strong>). Metoda va returna un intreg ce semnific\u0103 num\u0103rul a structurii bazei de date (<strong>CREATE<\/strong>, <strong>ALTER<\/strong>, <strong>DROP<\/strong>). Metoda va returna unde linii afectate de opera\u0163iunea de actualizare a datelor, sau 0 \u0131\u0302n cazul unei instruc\u0163iuni <em>DDL<\/em>.<\/p>\n<p><em>EFECTUAREA DE SECVEN\u0162E SQL<\/em><\/p>\n<p><em>String sql = &#8220;DELETE FROM persoane WHERE cod &gt; 100&#8221;;<\/em><br \/>\n<em>int linii = stmt.executeUpdate(sql);<\/em><br \/>\n<em>\/\/ Nr de articole care au fost afectate (sterse)<\/em><br \/>\n<em>sql = &#8220;DROP TABLE temp&#8221;;<\/em><br \/>\n<em>stmt.executeUpdate(sql); \/\/ returneaza 0<\/em><br \/>\n&nbsp;<br \/>\n<strong>3. execute<\/strong><\/p>\n<p>Aceast\u0103 metod\u0103 va fi folosit\u0103 doar dac\u00e2 este posibil ca rezultatul unei interog\u0103ri s\u0103 fie format din dou\u0103 sau mai multe obiecte de tip ResultSet sau rezultatul unei actualiz\u0103ri s\u0103 fie format din mai mule valori, sau o combina\u0163ie intre aceste cazuri. Aceast\u0103 situa\u0163ie, de\u015fi mai rar\u0103, este posibil\u0103 atunci c\u00e2nd sunt executate proceduri stocate sau secven\u0163e SQL cunoscute abia la momentul execu\u0163iei, programatorul ne\u015ftiind deci dac\u0103 va fi vorba de o actualizare a datelor sau a structurii. Metoda intoarce <em>true<\/em> dac\u0103 rezultatul ob\u0163inut este format din obiecte de tip <em>ResultSet<\/em> \u015fi <em>false<\/em> dac\u0103 e format din intregi.<br \/>\nIn func\u0163ie de aceasta, pot fi apelate metodele: <em>getResultSet<\/em> sau <em>getUpdateCount<\/em> pentru a afla efectiv rezultatul comenzii SQL. Pentru a prelua toate rezultatele va fi apelat\u0103 metoda <em>getMoreResults<\/em>, dup\u0103 care vor fi apelate din nou metodele amintite, p\u00e2n\u0103 la ob\u0163inerea valorii null, respectiv \u22121. Secven\u0163a complet\u0103 de tratare a metodei execute este prezentat\u0103 mai jos:<\/p>\n<p><em>String sql = &#8220;comanda SQL necunoscuta&#8221;;<\/em><br \/>\n<em>stmt.execute(sql);<\/em><br \/>\n<em>while(true) {<\/em><br \/>\n<em>int rowCount = stmt.getUpdateCount();<\/em><br \/>\n<em>if(rowCount &gt; 0) {<\/em><br \/>\n<em>\/\/ Este o actualizare datelor<\/em><br \/>\n<em>System.out.println(&#8220;Linii afectate = &#8221; + rowCount);<\/em><br \/>\n<em>stmt.getMoreResults();<\/em><br \/>\n<em>continue;<\/em><br \/>\n<em>}<\/em><br \/>\n<em>if(rowCount = 0) {<\/em><br \/>\n<em>\/\/ Comanda DDL sau nici o linie afectata<\/em><br \/>\n<em>System.out.println(&#8220;Comanda DDL sau 0 actualizari&#8221;);<\/em><\/p>\n<p><em>stmt.getMoreResults();<\/em><br \/>\n<em>continue;<\/em><br \/>\n<em>}<\/em><br \/>\n<em>\/\/ rowCount este -1<\/em><br \/>\n<em>\/\/ Avem unul sau mai multe ResultSet-uri<\/em><br \/>\n<em>ResultSet rs = stmt.getResultSet();<\/em><br \/>\n<em>if(rs != null) {<\/em><br \/>\n<em>\/\/ Proceseaza rezultatul<\/em><br \/>\n<em>&#8230;<\/em><br \/>\n<em>stmt.getMoreResults();<\/em><br \/>\n<em>continue;<\/em><br \/>\n<em>}<\/em><br \/>\n<em>\/\/ Nu mai avem nici un rezultat<\/em><br \/>\n<em>break;<\/em><br \/>\n<em>}<\/em><\/p>\n<p>Folosind clasa Statement, \u0131\u0302n cazul \u0131\u0302n care dorim s\u0103 introducem valorile unor variabile \u0131\u0302ntr-o secven\u0163\u0103 SQL, nu avem alt\u0103 solu\u0163ie dec\u00e2t s\u0103 cre\u0103m un \u015fir de caractere compus din instruc\u0163iuni SQL \u015fi valorile variabilelor:<\/p>\n<p><em>int cod = 100;<\/em><br \/>\n<em>String nume = &#8220;Popescu&#8221;;<\/em><br \/>\n<em>String sql = &#8220;SELECT * FROM persoane WHERE cod=&#8221; + cod +<\/em><br \/>\n<em>&#8221; OR nume=\u2019&#8221; + nume + &#8220;\u2019&#8221;;<\/em><br \/>\n<em>ResultSet rs = stmt.executeQuery(sql);<\/em><br \/>\n&nbsp;<br \/>\n<strong>Interfa\u0163a PreparedStatement<\/strong><\/p>\n<p>Interfa\u0163a PreparedStatement este derivat\u0103 din Statement, fiind diferit\u0103 deaceasta in urm\u0103toarele privin\u0163e:<\/p>\n<ul>\n<li>Instan\u0163ele de tip <em>PreparedStatement<\/em> con\u0163in secven\u0163e SQL care au fost deja compilate<\/li>\n<li>O secven\u0163\u0103 SQL specificat\u0103 unui obiect <em>PreparedStatement<\/em> poate s\u0103 aib\u0103 unul sau mai mul\u0163i parametri de intrare, care vor fi specifica\u0163i prin intermediul unui semn de intrebare (\u201d?\u201d) \u0131\u0302n locul fiec\u0103ruia dintre ei. Inainte ca secven\u0163a SQL s\u0103 poat\u0103 fi executat\u0103 fiec\u0103rui parametru de intrare trebuie s\u0103 i se atribuie o valoare, folosind metode specifice acestei clase.<\/li>\n<\/ul>\n<p>Execu\u0163ia repetat\u0103 a aceleia\u015fi secven\u0163e SQL, dar cu parametri diferi\u0163i, va fi in general mai rapid\u0103 dac\u0103 folosim <em>PreparedStatement<\/em>, deoarece nu mai trebuie s\u0103 cre\u0103m c\u00e2te un obiect de tip <em>Statement<\/em> pentru fiecare apel SQL, ci refolosim o singur\u0103 instan\u0163\u0103 precompilat\u0103 furniz\u00e2ndu-i doar alte argumente.<br \/>\nCrearea unui obiect de tip <em>PreparedStatement<\/em> se realizeaz\u0103 prin intermediul metodei <em>prepareStatement<\/em> a clasei <em>Connection<\/em>, specific\u00e2nd ca argument o secven\u0163\u0103 SQL ce con\u0163ine c\u0103te un semn de intrebare pentru fiecare parametru de intrare:<\/p>\n<p><em>Connection con = DriverManager.getConnection(url);<\/em><br \/>\n<em>String sql = &#8220;UPDATE persoane SET nume=? WHERE cod=?&#8221;;<\/em><br \/>\n<em>Statement pstmt = con.prepareStatement(sql);<\/em><\/p>\n<p>Obiectul va pstmt con\u0163ine o comand\u0103 SQL precompilat\u0103 care este trimis\u0103 imediat c\u0103tre baza de date, unde va a\u015ftepta parametri de intrare pentru a putea fi executat\u0103.<br \/>\nTrimiterea parametrilor se realizeaz\u0103 prin metode de tip setXXX, unde XXX este tipul corespunz\u0103tor parametrului, iar argumentele metodei sunt num\u0103rul de ordine al parametrului de intrare (al semnului de intrebare) \u015fi valoarea pe care dorim s\u0103 o atribuim.<\/p>\n<p><em>pstmt.setString(1, &#8220;Ionescu&#8221;);<\/em><br \/>\n<em>pstmt.setInt(2, 100);<\/em><\/p>\n<p>Dup\u0103 stabilirea parametrilor de intrare secven\u0163a <em>SQL<\/em> poate fi executat\u0103. Putem apoi stabili alte valori de intrare \u015fi refolosi obiectul <em>PreparedStatement<\/em> pentru execu\u0163ii repetate ale comenzii <em>SQL<\/em>. Este ins\u0103 posibil ca SGBD-ul folosit s\u0103 nu suporte acest tip de opera\u0163iune \u015fi s\u0103 nu re\u0163in\u0103 obiectul precompilat pentru execu\u0163ii ulterioare. In aceast\u0103 situa\u0163ie folosirea interfe\u0163ei <em>PreparedStatement<\/em> in loc de <em>Statement<\/em> nu va imbun\u0103t\u0103\u0163i in nici un fel performan\u0163a codului, din punctul de vedere al vitezei de execu\u0163ie a acestuia.<br \/>\nExecu\u0163ia unei secven\u0163e <em>SQL<\/em> folosind un obiect <em>PreparedStatement<\/em> se realizeaz\u0103 printr-una din metodele <em>executeQuery<\/em>, <em>executeUpdate<\/em> sau execute, semnifica\u0163iile lor fiind acelea\u015fi ca \u015fi \u0131\u0302n cazul obiectelor de tip<br \/>\n<em>Statement<\/em>, cu singura deosebire c\u0103 in cazul de fa\u0163\u0103 ele nu au nici un argument.<\/p>\n<p><em>String sql = &#8220;UPDATE persoane SET nume=? WHERE cod=?&#8221;;<\/em><br \/>\n<em>Statement pstmt = con.prepareStatement(sql);<\/em><br \/>\n<em>pstmt.setString(1, &#8220;Ionescu&#8221;);<\/em><br \/>\n<em>pstmt.setInt(2, 100);<\/em><br \/>\n<em>pstmt.executeUpdate();<\/em><br \/>\n<em>pstmt.setString(1, &#8220;Popescu&#8221;);<\/em><br \/>\n<em>pstmt.setInt(2, 200);<\/em><br \/>\n<em>pstmt.executeUpdate();<\/em><br \/>\n<em>sql = &#8220;SELECT * from persoane WHERE cod &gt;= ?&#8221;;<\/em><br \/>\n<em>pstmt = con.prepareStatement(sql);<\/em><br \/>\n<em>pstmt.setInt(1, 100);<\/em><br \/>\n<em>ResultSet rs = pstmt.executeQuery();<\/em><\/p>\n<p>Fiec\u0103rui tip Java ii corespunde un tip generic <em>SQL<\/em>. Este responsabilitatea programatorului s\u0103 se asigure c\u0103 folose\u015fte metoda adecvat\u0103 de tip setXXX la stabilirea valorii unui parametru de intrare. Lista tuturor tipurilor generice disponibile, numite \u015fi tipuri JDBC, este definit\u0103 de clasa <em>Types<\/em>, prin constantelor declarate de aceasta. Metoda <em>setObject<\/em> permite specificarea unor valori pentru parametrii de intrare, atunci c\u00e2nd dorim s\u0103 folosim maparea implicit\u0103 intre tipurile Java \u015fi cele JDBC sau atunci c\u00e2nd dorim s\u0103 preciz\u0103m explicit un tip JDBC.<\/p>\n<p><em>pstmt.setObject(1, &#8220;Ionescu&#8221;, Types.CHAR);<\/em><br \/>\n<em>pstmt.setObject(2, 100, Types.INTEGER); \/\/ sau doar<\/em><br \/>\n<em>pstmt.setObject(2, 100);<\/em><\/p>\n<p>Folosind metoda <em>setNull<\/em> putem s\u0103 atribuim unui parametru de intrare valoare <em>SQL NULL<\/em>, trebuind \u0131\u0302ns\u0103 s\u0103 specific\u0103m \u015fi tipul de date al coloanei in care vom scrie aceast\u0103 valoare. Acela\u015fi lucru poate fi realizat cu metode de tipul <em>setXXX<\/em> dac\u0103 argumentul folosit are valoarea <em>null<\/em>.<\/p>\n<p><em>pstmt.setNull(1, Types.CHAR);<\/em><br \/>\n<em>pstmt.setInt(2, null);<\/em><\/p>\n<p>Cu ajutorul metodelor <em>setBytes<\/em> sau <em>setString<\/em> avem posibilitatea de a specifica date de orice dimensiuni ca valori pentru anumite articole din baza de date. Exist\u0103 ins\u0103 situa\u0163ii c\u00e2nd este de preferat ca datele de mari dimensi uni s\u0103 fie transferate pe \u201dbuc\u0103\u0163i\u201d de o anumit\u0103 dimensiune. Pentru a realiza acest lucru API-ul JDBC pune la dispozi\u0163ie metodele <em>setBinaryStream,<\/em> <em>setAsciiStream<\/em> \u015fi <em>setUnicodeStream<\/em> care ata\u015feaz\u0103 un flux de intrare pe octe\u0163i, caractere ASCII, respectiv UNICODE, unui parametru de intrare. Pe m\u0103sur\u0103 ce sunt citite date de pe flux, ele vor fi atribuite parametrului. Exemplul de mai jos ilustreaz\u0103 acest lucru, atribuind coloanei continut con\u0163inutul unui anumit fi\u015fier:<\/p>\n<p><em>File file = new File(&#8220;date.txt&#8221;);<\/em><br \/>\n<em>int fileLength = file.length();<\/em><br \/>\n<em>InputStream fin = new FileInputStream(file);<\/em><br \/>\n<em>java.sql.PreparedStatement pstmt = con.prepareStatement(<\/em><br \/>\n<em>&#8220;UPDATE fisiere SET continut = ? WHERE nume = \u2019date.txt\u2019&#8221;);<\/em><br \/>\n<em>pstmt.setUnicodeStream (1, fin, fileLength);<\/em><br \/>\n<em>pstmt.executeUpdate();<\/em><\/p>\n<p>La execu\u0163ia secven\u0163ei, fluxul de intrare va fi apelat repetat pentru a furniza datele ce vor fi scrise in coloana continut a articolului specificat. Observa\u0163i c\u0103 este necesar \u0131\u0302n\u0103 s\u0103 \u015ftim dinainte dimensiunea datelor ce vor fi scrise, acest lucru fiind solicitat de unele tipuri de baze de date.<\/p>\n<p><strong>Interfa\u0163a CallableStatement<\/strong><br \/>\nInterfa\u0163a <em>CallableStatement<\/em> este derivat\u0103 din <em>PreparedStatement<\/em>, instan\u0163ele de acest tip oferind o modalitate de a apela o procedur\u0103 stocat\u0103 intr-o baz\u0103 de date, intr-o manier\u0103 standar pentru toate SGBD-urile.<br \/>\nCrearea unui obiect <em>CallableStatement<\/em> se realizeaz\u0103 prin metoda <em>prepareCall<\/em> a clasei <em>Connection<\/em>:<\/p>\n<p><em>Connection con = DriverManager.getConnection(url);<\/em><br \/>\n<em>CallableStatement cstmt = con.prepareCall(<\/em><br \/>\n<em>&#8220;{call proceduraStocata(?, ?)}&#8221;);<\/em><\/p>\n<p>Trimiterea parametrilor de intrare se realizeaz\u0103 intocmai ca la <em>PreparedStatement,<\/em> cu metode de tip <em>setXXX<\/em>. Dac\u0103 procedura are \u015fi parametri de ie\u015fire (valori returnate), ace\u015ftia vor trebui inregistra\u0163i cu metoda <em>registerOutParameter<\/em> inainte de execu\u0163ia procedurii. Ob\u0163inerea valorilor rezultate in parametrii de ie\u015fie se va face cu metode de tip getXXX.<\/p>\n<p><em>CallableStatement cstmt = con.prepareCall(<\/em><\/p>\n<p><em>&#8220;{call calculMedie(?)}&#8221;);<\/em><br \/>\n<em>cstmt.registerOutParameter(1, java.sql.Types.FLOAT);<\/em><br \/>\n<em>cstmt.executeQuery();<\/em><br \/>\n<em>float medie = cstmt.getDouble(1);<\/em><\/p>\n<p>Este posibil ca un parametru de intrare s\u0103 fie \u015fi parametru de ie\u015fire. In acest caz el trebuie s\u0103 primeasc\u0103 o valoare cu <em>setXXX<\/em> \u015fi, de asemenea, va fi inregistrat cu <em>registerOutParameter<\/em>, tipurile de date specificate trebuind s\u0103 coincid\u0103.<br \/>\n&nbsp;<br \/>\n<strong>Ob\u0163inerea \u015fi prelucrarea rezultatelor<\/strong><br \/>\n<strong>Interfa\u0163a ResultSet<\/strong><\/p>\n<p>In urma execu\u0163ie unei interog\u0103ri SQL rezultatul va fi reprezentat printr-un obiect de tip<em> ResultSet,<\/em> ce va con\u0163ine toate liniile ce satisfac condi\u0163iile impuse de comanda SQL. Forma general\u0103 a unui <em>ResultSet<\/em> este tabelar\u0103, av\u00e2nd un num\u0103r de coloane \u015fi de linii, func\u0163ie de secven\u0163a executat\u0103. De asemenea, obiectul va con\u0163ine \u015fi meta-datele interog\u0103rii cum ar fi denumirele coloanelor selectate si num\u0103rul lor.<\/p>\n<p><em>Statement stmt = con.createStatement();<\/em><br \/>\n<em>String sql = &#8220;SELECT cod, nume FROM persoane&#8221;;<\/em><br \/>\n<em>ResultSet rs = stmt.executeQuery(sql);<\/em><\/p>\n<p>Rezultatul interog\u0103rii de mai sus va fi obiectul <em>rs<\/em> cu urm\u0103toarea structur\u0103:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/eugo.ro\/Baze-date\/IMG\/6.png\" alt=\"\" \/><br \/>\nPentru a extrage informa\u0163iile din aceast\u0103 structur\u0103 va trebui s\u0103 parcurgem tabelul linie cu linie \u015fi din fiecare s\u0103 extragem valorile de pe coloane. Pentru acest lucru vom folosi metode de tip getXXX, unde XXX este tipul de dat\u0103 al unei coloane iar argumentul primit indic\u0103 fie num\u0103rul de ordine din cadrul tabelului, fie numele acestuia. Coloanele sunt numerotate de la st\u00e2nga la dreapta, \u0131\u0302ncep\u00e2nd cu 1. In general, folosirea indexului coloanei in loc de numele s\u0103u va fi mai eficient\u0103. De asemenea, pentru maxim\u0103 portabilitate se recomand\u0103 citirea coloanelor in ordine de la st\u00e2nga la dreapta \u015fi fiecare citire s\u0103 se fac\u0103 o singur\u0103 dat\u0103.<\/p>\n<p>Un obiect <em>ResultSet<\/em> folose\u015fte un cursor pentru a parcurge articolele rezultate in urma unei interog\u0103ri. Ini\u0163ial acest cursor este pozi\u0163ionat inaintea primei linii, fiecare apel al metodei next determin\u00e2nd trecerea la urm\u0103toarea linie. Deoarece next returneaz\u0103 false c\u00e2nd nu mai sunt linii de adus, uzual va fi folosit\u0103 o bucl\u0103 while-loop petru a itera prin articolele tabelului:<\/p>\n<p><em>String sql = &#8220;SELECT cod, nume FROM persoane&#8221;;<\/em><br \/>\n<em>ResultSet rs = stmt.executeQuery(sql);<\/em><br \/>\n<em>while (rs.next()) {<\/em><br \/>\n<em>int cod = r.getInt(&#8220;cod&#8221;);<\/em><br \/>\n<em>String nume = r.getString(&#8220;nume&#8221;);<\/em><br \/>\n<em>\/* echivalent:<\/em><br \/>\n<em>int cod = r.getInt(1);<\/em><br \/>\n<em>String nume = r.getString(2);<\/em><br \/>\n<em>*\/<\/em><br \/>\n<em>System.out.println(cod + &#8220;, &#8221; + nume);<\/em><br \/>\n<em>}<\/em><\/p>\n<p>Implicit, un tabel de tip <em>ResultSet<\/em> nu poate fi modificat iar cursorul asociat nu se deplaseaz\u0103 dec\u00e2t inainte, linie cu linie. A\u015fadar, putem itera prin rezultatul unei interog\u0103ri o singur\u0103 dat\u0103 \u015fi numai de la prima la ultima linie. Este ins\u0103 posibil s\u0103 cre\u0103m ResultSet-uri care s\u0103 permit\u0103 modificarea sau deplasarea in ambele sensuri. Exemplul urm\u0103tor va folosi un cursor care este modificabil \u015fi nu va reflecta schimb\u0103rile produse de al\u0163i utilizatori dup\u0103 crearea sa:<\/p>\n<p><em>Statement stmt = con.createStatement(<\/em><br \/>\n<em>ResultSet.TYPE_SCROLL_INSENSITIVE,<\/em><br \/>\n<em>ResultSet.CONCUR_UPDATABLE);<\/em><br \/>\n<em>String sql = &#8220;SELECT cod, nume FROM persoane&#8221;;<\/em><br \/>\n<em>ResultSet rs = stmt.executeQuery(sql);<\/em><\/p>\n<p>Dac\u0103 un <em>ResultSet<\/em> folose\u015fte un cursor modificabil \u015fi care poate naviga in ambele sensuri, atunci are la dispozi\u0163ie o serie de metode ce se bazeaz\u0103 pe acest suport:<\/p>\n<ul>\n<li><strong>absolute<\/strong> &#8211; Deplaseaz\u0103 cursorul la o anumit\u0103 linie specificat\u0103 absolut;<\/li>\n<li><strong>updateXXX<\/strong> &#8211; Actualizeaz\u0103 valoarea unei coloane din linia curent\u0103, unde <em>XXX<\/em> este un tip de date.<\/li>\n<li><strong>updateRow<\/strong> &#8211; Transfer\u0103 actualiz\u0103rile f\u0103cute liniei \u0131\u0302n baza de date.<\/li>\n<li><strong>moveToInsertRow<\/strong> &#8211; deplaseaz\u0103 cursorul la o linie special\u0103, numit\u0103 linie nou\u0103, utilizate\u0103 pentru a introduce noi articole in baza de date. Linia curent\u0103 anterioar\u0103 a cursorului va fi memorat\u0103 pentru a se putea reveni la ea.<\/li>\n<li><strong>insertRow<\/strong> &#8211; insereaz\u0103 articolul din zona linie nou\u0103 in baza de date; cursorul trebuie s\u0103 fie pozi\u0163ionat le linia nou\u0103 la execu\u0163ia acestei opera\u0163iuni.<\/li>\n<li><strong>moveToCurrentRow<\/strong> &#8211; revine la linia curent\u0103 din tabel.<\/li>\n<li><strong>deleteRow<\/strong> &#8211; \u015fterge linia curent\u0103 din tabel \u015fi din baza de date; nu poate fi apelat\u0103 c\u00e2nd cursorul este in modul linie nou\u0103.<\/li>\n<\/ul>\n<p>Nu toate sistemele de gestiune a bazelor de date ofer\u0103 suport pentru folosirea cursoarelor care pot fi modificate. Pentru a determina dac\u0103 baza de date permite acest lucru pot fi utilizate metodele <em>supportsPositionedUpdate<\/em> \u015fi <em>supportsPositionedDelete<\/em> ale clasei <em>DatabaseMetaData<\/em>. In cazul in care acest lucru este permis, este responsabilitatea driver-ului bazei de date s\u0103 asigure rezolvarea problemelor legate de actualizarea concurent\u0103 a unui cursor, astfel inc\u00e2t s\u0103 nu apar\u0103 anomalii.<br \/>\n&nbsp;<br \/>\n<strong>Un exemplu simplu<\/strong><\/p>\n<p>In continuare vom da un exemplul simplu de utilizare a claselor de baz\u0103 men\u0163ionate anterior. Programul va folosi o baz\u0103 de date MySql, ce con\u0163ine un tabel numit persoane, av\u00e2nd coloanele: cod, nume \u015fi salariu. Scriptul SQL de creare a bazei este:<\/p>\n<p><em>create table persoane(cod integer, nume char(50), salariu double);<\/em><\/p>\n<p>Aplica\u0163ia va goli tabelul cu persoane, dup\u0103 care va ad\u0103uga aleator un num\u0103r de articole, va efectua afi\u015farea lor \u015fi calculul mediei salariilor.<br \/>\n&nbsp;<br \/>\n<strong><em>Exemplu simplu de utilzare JDBC<\/em><\/strong><\/p>\n<p><em>import java . sql .*;<\/em><br \/>\n<em>public class TestJdbc {<\/em><br \/>\n<em>public static void main ( String [] args ) {<\/em><\/p>\n<p><em>String url = &#8221; jdbc : mysql :\/\/ localhost \/ test &#8221; ;<\/em><br \/>\n<em>try {<\/em><br \/>\n<em>Class . forName ( &#8221; com . mysql . jdbc . Driver &#8221; ) ;<\/em><br \/>\n<em>} catch ( ClassNotFoundException e ) {<\/em><br \/>\n<em>System . out . println ( &#8221; Eroare incarcare driver !\\ n &#8221; + e ) ;<\/em><br \/>\n<em>return ;<\/em><br \/>\n<em>}<\/em><br \/>\n<em>try {<\/em><br \/>\n<em>Connection con = DriverManager . getConnection ( url ) ;<\/em><br \/>\n<em>\/\/ Golim tabelul persoane<\/em><br \/>\n<em>String sql = &#8221; DELETE FROM persoane &#8221; ;<\/em><br \/>\n<em>Statement stmt = con . createStatement () ;<\/em><br \/>\n<em>stmt . executeUpdate ( sql ) ;<\/em><br \/>\n<em>\/\/ Adaugam un numar de persoane generate aleator<\/em><br \/>\n<em>\/\/ Tabelul persoane are coloanele ( cod , nume , salariu )<\/em><br \/>\n<em>int n = 10;<\/em><br \/>\n<em>sql = &#8221; INSERT INTO persoane VALUES (? , ? , ?) &#8221; ;<\/em><br \/>\n<em>PreparedStatement pstmt = con . prepareStatement ( sql ) ;<\/em><br \/>\n<em>for ( int i =0; i &lt; n ; i ++) {<\/em><br \/>\n<em>int cod = i ;<\/em><br \/>\n<em>String nume = &#8221; Persoana &#8221; + i ;<\/em><br \/>\n<em>double salariu = 100 + Math . round ( Math . random () *<\/em><br \/>\n<em>900) ;<\/em><br \/>\n<em>\/\/ salariul va fi intre 100 si 1000<\/em><br \/>\n<em>pstmt . setInt (1 , cod ) ;<\/em><br \/>\n<em>pstmt . setString (2 , nume ) ;<\/em><br \/>\n<em>pstmt . setDouble (3 , salariu ) ;<\/em><br \/>\n<em>pstmt . executeUpdate () ;<\/em><br \/>\n<em>}<\/em><br \/>\n<em>\/\/ Afisam persoanele ordonate dupa salariu<\/em><br \/>\n<em>sql = &#8221; SELECT * FROM persoane ORDER BY salariu &#8221; ;<\/em><br \/>\n<em>ResultSet rs = stmt . executeQuery ( sql ) ;<\/em><br \/>\n<em>while ( rs . next () )<\/em><br \/>\n<em>System . out . println ( rs . getInt ( &#8221; cod &#8221; ) + &#8221; , &#8221; +<\/em><br \/>\n<em>rs . getString ( &#8221; nume &#8221; ) + &#8221; , &#8221; +<\/em><br \/>\n<em>rs . getDouble ( &#8221; salariu &#8221; ) ) ;<\/em><br \/>\n<em>\/\/ Calculam salariul mediu<\/em><br \/>\n<em>sql = &#8221; SELECT avg ( salariu ) FROM persoane &#8221; ;<\/em><br \/>\n<em>rs = stmt . executeQuery ( sql ) ;<\/em><br \/>\n<em>rs . next () ;<\/em><\/p>\n<p><em>System . out . println ( &#8221; Media : &#8221; + rs . getDouble (1) ) ;<\/em><br \/>\n<em>\/\/ Inchidem conexiunea<\/em><br \/>\n<em>con . close () ;<\/em><br \/>\n<em>} catch ( SQLException e ) {<\/em><br \/>\n<em>e . printStackTrace () ;<\/em><br \/>\n<em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/em><br \/>\n<em>\u00a0\u00a0\u00a0 }<\/em><br \/>\n<em>}<\/em><br \/>\n&nbsp;<br \/>\n<strong>Lucrul cu meta-date<\/strong><br \/>\n<strong>Interfa\u0163a DatabaseMetaData<\/strong><\/p>\n<p>Dup\u0103 realizarea unui conexiuni la o baz\u0103 de date, putem apela metoda getMetaData pentru a afla diverse informa\u0163ii legate de baza respectiv\u0103, a\u015fa numitele meta-date (\u201ddate despre date\u201d); Ca rezult al apelului metodei, vom ob\u0163ine un obiect de tip DatabaseMetaData ce ofer\u0103 metode pentru determinarea tabelelor, procedurilor stocate, capabilit\u0103\u0163ilor conexiunii, gramaticii SQL suportate, etc. ale bazei de date.<br \/>\nProgramul urm\u0103tor afi\u015feaz\u0103 numele tuturor tabelelor dintr-o baz\u0103 de dat inregistrat\u0103 in ODBC.<\/p>\n<p><strong><em>Folosirea interfe\u0163ei DatabaseMetaData<\/em><\/strong><\/p>\n<p><em>import java . sql .*;<\/em><br \/>\n<em>public class TestMetaData {<\/em><br \/>\n<em>public static void main ( String [] args ) {<\/em><br \/>\n<em>String url = &#8221; jdbc : odbc : test &#8221; ;<\/em><br \/>\n<em>try {<\/em><br \/>\n<em>Class . forName ( &#8221; sun . jdbc . odbc . JdbcOdbcDriver &#8221; ) ;<\/em><br \/>\n<em>} catch ( ClassNotFoundException e ) {<\/em><br \/>\n<em>System . out . println ( &#8221; Eroare incarcare driver !\\ n &#8221; + e ) ;<\/em><br \/>\n<em>return ;<\/em><br \/>\n<em>}<\/em><\/p>\n<p><em>\u00a0\u00a0\u00a0 }<\/em><br \/>\n<em>}<\/em><\/p>\n<p><em><strong>Interfa\u0163a ResultSetMetaD<\/strong><\/em><\/p>\n<p><em>try {<\/em><br \/>\n<em>Connection con = DriverManager . getConnection ( url ) ;<\/em><br \/>\n<em>DatabaseMetaData dbmd = con . getMetaData () ;<\/em><br \/>\n<em>ResultSet rs = dbmd . getTables ( null , null , null , null ) ;<\/em><\/p>\n<p><em>while ( rs . next () )<\/em><br \/>\n<em>System . out . println ( rs . getString ( &#8221; TABLE_NAME &#8221; ) ) ;<\/em><br \/>\n<em>con . close () ;<\/em><br \/>\n<em>} catch ( SQLException e ) {<\/em><br \/>\n<em>e . printStackTrace () ;<\/em><br \/>\n<em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/em><br \/>\n<em>\u00a0\u00a0\u00a0 }<\/em><br \/>\n<em>}<\/em><br \/>\n&nbsp;<br \/>\n<em><strong>Interfa\u0163a ResultSetMetaData<\/strong><\/em><\/p>\n<p><strong>Meta-datele<\/strong> unui <em>ResultSet<\/em> reprezint\u0103 informa\u0163iile despre rezultatul con\u0163inut in acel obiect cum ar fi num\u0103rul coloanelor, tipul \u015fi denumirile lor, etc. Acestea sunt ob\u0163inute apel\u00e2nd metoda <em>getMetaData<\/em> pentru ResultSet-ul respectiv, care va returna un obiect de tip <em>ResultSetMetaData<\/em> ce poate fi apoi folosit pentru extragerea informa\u0163iilor dorite.<\/p>\n<p><em>ResultSet rs = stmt.executeQuery(&#8220;SELECT * FROM tabel&#8221;);<\/em><br \/>\n<em>ResultSetMetaData rsmd = rs.getMetaData();<\/em><br \/>\n<em>\/\/ Aflam numarul de coloane<\/em><br \/>\n<em>int n = rsmd.getColumnCount();<\/em><br \/>\n<em>\/\/ Aflam numele coloanelor<\/em><br \/>\n<em>Sring nume[] = new String[n+1];<\/em><br \/>\n<em>for(int i=1; i&lt;=n; i++)<\/em><br \/>\n<em>nume[i] = rsmd.getColumnName(i);<\/em><br \/>\n<!-- Start of StatCounter Code --><br \/>\n  <script type=\"text\/javascript\">\nvar sc_project=5241295; \nvar sc_invisible=1; \nvar sc_security=\"f184e0a9\"; \n    <\/script><br \/>\n  <script type=\"text\/javascript\"\nsrc=\"http:\/\/www.statcounter.com\/counter\/counter.js\"><\/script><br \/>\n  <noscript><br \/>\n  <\/noscript>\n<\/div>\n<p><noscript><\/p>\n<div\nclass=\"statcounter\"><\/p>\n<div align=\"center\"><a title=\"weebly reliable statistics\"\nhref=\"http:\/\/www.statcounter.com\/weebly\/\"\ntarget=\"_blank\"><img class=\"statcounter\"\nsrc=\"http:\/\/c.statcounter.com\/5241295\/0\/f184e0a9\/1\/\"\nalt=\"weebly reliable statistics\" ><\/a><\/div>\n<\/div>\n<p><\/noscript><\/p>\n<div align=\"center\">\n    <!-- End of StatCounter Code --><\/p>\n<h6 style=\"text-align: right;\"><em>Material preluat din Curs practic de Java-Cristian Frasinaru<\/em><\/h6>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Aplica\u0163iile care folosesc baze de date sunt, in general, aplica\u0163ii complexe folosite pentru gestionarea unor informa\u0163ii de dimensiuni mari intr-o manier\u0103 sigur\u0103 \u015fi eficient\u0103. &nbsp; Ce este o baz\u0103 de date ? La nivelul cel mai general, o baz\u0103 de date reprezint\u0103 o modalitate de stocare a unor informa\u0163ii (date) pe un suport extern, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[],"class_list":["post-434","post","type-post","status-publish","format-standard","hentry","category-baze-de-date"],"_links":{"self":[{"href":"https:\/\/eugo.ro\/index.php?rest_route=\/wp\/v2\/posts\/434","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/eugo.ro\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eugo.ro\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eugo.ro\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/eugo.ro\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=434"}],"version-history":[{"count":100,"href":"https:\/\/eugo.ro\/index.php?rest_route=\/wp\/v2\/posts\/434\/revisions"}],"predecessor-version":[{"id":566,"href":"https:\/\/eugo.ro\/index.php?rest_route=\/wp\/v2\/posts\/434\/revisions\/566"}],"wp:attachment":[{"href":"https:\/\/eugo.ro\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=434"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eugo.ro\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=434"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eugo.ro\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=434"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}