Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
laboratoare:laborator01 [2015/10/18 18:58]
Andrei Roșu-Cojocaru [Integrarea manuală a bibliotecilor dependente]
laboratoare:laborator01 [2015/10/19 00:44] (current)
Andrei Roșu-Cojocaru [Materiale Ajutătoare]
Line 18: Line 18:
 ===== Materiale Ajutătoare ====== ===== Materiale Ajutătoare ======
  
-TODO+{{ :​laboratoare:​laborator01:​aipi2015-lab01-slides.pdf }}
  
 ===== Java Database Connectivity - aspecte generale ===== ===== Java Database Connectivity - aspecte generale =====
Line 101: Line 101:
 ==== Maven ==== ==== Maven ====
  
-Proiectul poate fi integrat cu [[https://​maven.apache.org/​|Apache Maven]], un utilitar automat prin care se descriu mecanismele prin care aplicațiile Java sunt compilate, instalate, rulate și testate dar și dependințele de diferite biblioteci.+Proiectul poate fi integrat cu [[https://​maven.apache.org/​|Apache Maven]], un utilitar automat prin care se descriu mecanismele prin care aplicațiile Java sunt compilate, instalate, rulate și testate dar și dependențele de diferite biblioteci.
  
 Documentul în care sunt descrise proprietățile proiectului se numește ''​pom.xml''​ și trebuie plasat în rădăcina sistemului de fișiere. Documentul în care sunt descrise proprietățile proiectului se numește ''​pom.xml''​ și trebuie plasat în rădăcina sistemului de fișiere.
Line 154: Line 154:
 ==== Integrarea manuală a bibliotecilor dependente ==== ==== Integrarea manuală a bibliotecilor dependente ====
  
-  * Eclipse Mars (4.5) +=== Eclipse Mars (4.5) === 
-    * clasele conţinute în arhiva .jar trebuie adăugate la calea proiectului + 
-      * în cazul în care arhiva .jar nu se găseşte în structura proiectului:​ +  ​* clasele conţinute în arhiva .jar trebuie adăugate la calea proiectului 
-        * click dreapta pe numele bibliotecii → //Build Path// → //Configure Build Path...//\\ {{ :​laboratoare:​laborator01:​04eclipse_project_configuration01.png?​nolink&​500 }} +    * în cazul în care arhiva .jar nu se găseşte în structura proiectului:​ 
-        * în secțiunea //Java Build Path// a proprietăților proiectului,​ în panoul de prezentare //​Libraries//,​ se accesează butonul //Add JARs...// (dacă biblioteca se găsește în sistemul de fișiere al proiectului),​ respectiv butonu //Add External JARs...// (dacă biblioteca nu se găsește în sistemul de fișiere al proiectului)\\ {{ :​laboratoare:​laborator01:​04eclipse_project_configuration02.png?​nolink&​500 ​}} +      * click dreapta pe numele bibliotecii → //Build Path// → //Configure Build Path...//\\ {{ :​laboratoare:​laborator01:​04eclipse_project_configuration01.png?​nolink&​500 }} 
-        * se selectează arhiva .jar care conține biblioteca necesară\\ {{ :​laboratoare:​laborator01:​04eclipse_project_configuration03.png?​nolink }} +      * în secțiunea //Java Build Path// a proprietăților proiectului,​ în panoul de prezentare //​Libraries//,​ se accesează butonul //Add JARs...// (dacă biblioteca se găsește în sistemul de fișiere al proiectului),​ respectiv butonu //Add External JARs...// (dacă biblioteca nu se găsește în sistemul de fișiere al proiectului)\\ {{ :​laboratoare:​laborator01:​04eclipse_project_configuration02.png?​nolink }} 
-      * în cazul în care arhiva .jar există în structura proiectului:​ click dreapta pe numele proiectului → //Build Path// → //Add to Build Path//\\ {{ :​laboratoare:​laborator01:​04eclipse_project_configuration05.png?​nolink&​500 }} +      * se selectează arhiva .jar care conține biblioteca necesară\\ {{ :​laboratoare:​laborator01:​04eclipse_project_configuration03.png?​nolink }} 
-    * dacă biblioteca a fost adăugată în mod corect, denumirea acesteia trebuie să apară în secțiunea //Package Explorer//​\\ {{ :​laboratoare:​laborator01:​04eclipse_project_configuration04.png?​nolink&​300 ​}} +    * în cazul în care arhiva .jar există în structura proiectului:​ click dreapta pe numele proiectului → //Build Path// → //Add to Build Path//\\ {{ :​laboratoare:​laborator01:​04eclipse_project_configuration05.png?​nolink&​500 }} 
-  ​* ​NetBeans 8.0.2 +  * dacă biblioteca a fost adăugată în mod corect, denumirea acesteia trebuie să apară în secțiunea //Package Explorer//​\\ {{ :​laboratoare:​laborator01:​04eclipse_project_configuration04.png?​nolink }} 
-    * din meniul corespunzător proiectului,​ se selectează //​Libraries//,​ click dreapta şi se accesează opţiunea //Add JAR/​Folder//​\\ {{ :​laboratoare:​laborator02_figura04_netbeans01.png?nolink&​300 ​}} + 
-    * în fereastra de dialog se alege referinţa drept cale relativă (//​Reference As:// → //Relative Path//), în situația în care arhiva este localizată în sistemul de fişiere al proiectului,​ respectiv drept cale absolută, altfel\\ {{ :​laboratoare:​laborator02_figura04_netbeans02.png?nolink&​600 ​}} +=== NetBeans 8.0.2 === 
-    * dacă biblioteca externă a fost adăugată în mod corect, numele ei trebuie să apară în meniul din stânga corespunzător proiectului,​ secţiunea //​Libraries//​\\ {{ :​laboratoare:​laborator02_figura04_netbeans03.png?nolink&​300 ​}}+ 
 +  ​* din meniul corespunzător proiectului,​ se selectează //​Libraries//,​ click dreapta şi se accesează opţiunea //Add JAR/Folder...//\\ {{ :​laboratoare:​laborator01:​05netbeans_project_configuration01.png?nolink }} 
 +  * în fereastra de dialog se alege referinţa drept cale relativă (//​Reference As// → //Relative Path//), în situația în care arhiva este localizată în sistemul de fişiere al proiectului,​ respectiv drept cale absolută, altfel\\ {{ :​laboratoare:​laborator01:​05netbeans_project_configuration02.png?nolink }} 
 +  * dacă biblioteca externă a fost adăugată în mod corect, numele ei trebuie să apară în meniul din stânga corespunzător proiectului,​ secţiunea //​Libraries//​\\ {{ :​laboratoare:​laborator01:​05netbeans_project_configuration03.png?nolink }}
  
 <note tip>Este recomandat ca arhiva .jar corespunzătoare driver-ului MySQL Connector/J să fie plasată întotdeauna în structura de fișiere a proiectului (cu referirea corespunzătoare a acestuia), astfel încât să se asigure portabilitatea aplicației.</​note>​ <note tip>Este recomandat ca arhiva .jar corespunzătoare driver-ului MySQL Connector/J să fie plasată întotdeauna în structura de fișiere a proiectului (cu referirea corespunzătoare a acestuia), astfel încât să se asigure portabilitatea aplicației.</​note>​
Line 197: Line 200:
 </​code>​ </​code>​
  
-**Deschiderea unei conexiuni** se face prin metoda statică ''​getConnection''​ din ''​DriverManager'',​ care întoarce un obiect conexiune (''​Connection''​) la baza de date, acesta putând fi folosit ulterior pentru diferite interogări:​+**Deschiderea unei conexiuni** se face prin metoda statică ''​getConnection()''​ din ''​DriverManager'',​ care întoarce un obiect conexiune (''​Connection''​) la baza de date, acesta putând fi folosit ulterior pentru diferite interogări:​
  
 <code java> <code java>
 String DATABASE_CONNECTION = "​jdbc:​mysql://​localhost:​3306/​bookstore";​ String DATABASE_CONNECTION = "​jdbc:​mysql://​localhost:​3306/​bookstore";​
-Connection ​dbConnection ​= DriverManager.getConnection(DATABASE_CONNECTION);​+Connection ​connection ​= DriverManager.getConnection(DATABASE_CONNECTION);​
 </​code>​ </​code>​
  
Line 207: Line 210:
  
   * <code java>   * <code java>
-Connection ​dbConnection ​= DriverManager.getConnection(DATABASE_CONNECTION, ​username, password);+Connection ​connection ​= DriverManager.getConnection(DATABASE_CONNECTION, ​DATABASE_USERNAME, DATABASE_PASSWORD);
 </​code>​ </​code>​
  
   * <code java>   * <code java>
-Connection ​dbConnection ​=  +Connection ​connection ​= DriverManager.getConnection(DATABASE_CONNECTION + "?​user="​ + DATABASE_USERNAME ​+ "&​password="​ + DATABASE_PASSWORD);
-DriverManager.getConnection(DATABASE_CONNECTION+"?​user="​+username+"&​password="​+password);+
 </​code>​ </​code>​
  
   * <​code>​   * <​code>​
 Properties connectionProperties = new Properties();​ Properties connectionProperties = new Properties();​
-connectionProperties.put("​user",​username);​ +connectionProperties.put("​user",​ username);​ 
-connectionProperties.put("​password",​password);​ +connectionProperties.put("​password",​ password);​ 
-Connection ​dbConnection ​= DriverManager.getConnection(DATABASE_CONNECTION,​ connectionProperties);​+Connection ​connection ​= DriverManager.getConnection(DATABASE_CONNECTION,​ connectionProperties);​
 </​code>​ </​code>​
  
-Dacă driverele gestionate de interfaţa ''​Driver'' ​ recunosc URL-ul indicat drept parametru metodei ''​getConnection'',​ se stabileşte o legătură cu sistemul de gestiune pentru baza de date, întorcându-se o conexiune care poate fi utilizată pentru transmiterea de instrucţiuni Java Database Connection translatate ulterior în interogări către baza de date.+Dacă driverele gestionate de interfaţa ''​Driver''​ recunosc URL-ul indicat drept parametru metodei ''​getConnection()'',​ se stabileşte o legătură cu sistemul de gestiune pentru baza de date, întorcându-se o conexiune care poate fi utilizată pentru transmiterea de instrucţiuni Java Database Connection translatate ulterior în interogări către baza de date.
  
-**Închiderea unei conexiuni**,​ prin care sunt eliberate toate resursele asociate acesteia, se face prin metoda ''​close'':​+**Închiderea unei conexiuni**,​ prin care sunt eliberate toate resursele asociate acesteia, se face prin metoda ''​close()'':​
 <code java> <code java>
-dbConnection.close();+if (connection != null && !connection.isClosed()) { 
 +  connection.close(); 
 +}
 </​code>​ </​code>​
  
Line 241: Line 245:
  
 <code java> <code java>
-Statement statement = dbConnection.createStatement();​+Statement statement = connection.createStatement();​
 </​code>​ </​code>​
  
Line 247: Line 251:
  
 <code java> <code java>
-try (Statement statement = dbConnection.createStatement()) {+try (Statement statement = connection.createStatement()) {
     ...     ...
 } }
Line 256: Line 260:
 String query = "​SELECT personal_identifier,​ first_name, last_name FROM user"; String query = "​SELECT personal_identifier,​ first_name, last_name FROM user";
 boolean result = statement.execute(query);​ boolean result = statement.execute(query);​
-if (result) +if (result) ​{ 
-    ResultSet records = statement.getResultSet();​+  ResultSet records = statement.getResultSet();​ 
 +}
 </​code>​ </​code>​
   * metoda ''​executeQuery()'':​ întoarce un singur obiect de tip ''​ResultSet'';​ <code java>   * metoda ''​executeQuery()'':​ întoarce un singur obiect de tip ''​ResultSet'';​ <code java>
-String query = "​SELECT COUNT(*) FROM invoice";+String query = "​SELECT COUNT(*) FROM invoice_header";
 ResultSet result = statement.executeQuery(query);​ ResultSet result = statement.executeQuery(query);​
 </​code>​ </​code>​
   * metoda ''​executeUpdate()'':​ întoarce un număr întreg având semnificaţia înregistrărilor afectate de expresia SQL; este folosită de regulă pentru instrucţiuni DML de tip ''​INSERT'',​ ''​UPDATE'',​ ''​DELETE'',​ dar şi pentru instrucţiuni de tip DDL precum ''​CREATE TABLE'',​ ''​ALTER TABLE'',​ ''​DROP TABLE'':​ <code java>   * metoda ''​executeUpdate()'':​ întoarce un număr întreg având semnificaţia înregistrărilor afectate de expresia SQL; este folosită de regulă pentru instrucţiuni DML de tip ''​INSERT'',​ ''​UPDATE'',​ ''​DELETE'',​ dar şi pentru instrucţiuni de tip DDL precum ''​CREATE TABLE'',​ ''​ALTER TABLE'',​ ''​DROP TABLE'':​ <code java>
-String query = "​CREATE TABLE series ​( +String query = "​CREATE TABLE category ​( 
-                              id          INT(10) UNSIGNED AUTO_INCREMENT ​PRIMARY KEY NOT NULL, +    id          INT(10) UNSIGNED AUTO_INCREMENT NOT NULL, 
-                              name        VARCHAR(100) NOT NULL, +    name        VARCHAR(50) NOT NULL, 
-                              description VARCHAR(1000) +    description VARCHAR(1000), 
-                                    );";+    KEY (id) 
 +);";
 int result = statement.executeUpdate(query);​ int result = statement.executeUpdate(query);​
 // ... // ...
-String query = "​INSERT INTO publishing_house (name, registered_number,​ description, ​town, region, country) +String query = "​INSERT INTO publishing_house (name, registered_number,​ description, ​postal_address, zip_code, country_id, internet_address) 
- ​VALUES('​Grupo Planeta', '892687559', '​-',​ 'Rome', '​Lazio'​, 'Italy');"+ ​VALUES('​Aardvark Global Publishing', '385231702', '​-',​ 'Santa Cruz, Santa Cruz County, CA', 95061, 187, null);"
 int result = statement.executeUpdate(query);​ int result = statement.executeUpdate(query);​
 </​code>​ </​code>​
Line 307: Line 313:
  
 <code java> <code java>
-Statement statement = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,​ +Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,​ 
-                                                   ​ResultSet.CONCUR_READ_ONLY,​ +                                                 ​ResultSet.CONCUR_READ_ONLY,​ 
-                                                   ​ResultSet.HOLD_CURSORS_OVER_COMMIT);​+                                                 ​ResultSet.HOLD_CURSORS_OVER_COMMIT);​
 </​code>​ </​code>​
  
Line 352: Line 358:
  
 <code java> <code java>
-Statement statement = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,​ +Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,​ 
-                                                   ​ResultSet.CONCUR_UPDATABLE);​ +                                                 ​ResultSet.CONCUR_UPDATABLE);​
 ResultSet result = statement.executeQuery("​SELECT * FROM writer"​);​ ResultSet result = statement.executeQuery("​SELECT * FROM writer"​);​
 result.moveToInsertRow();​ result.moveToInsertRow();​
-result.updateString(1,"​Sterne"​);​ +result.updateString(1,​ "​Sterne"​);​ 
-result.updateString(2,"​Laurence"​);​+result.updateString(2,​ "​Laurence"​);​
 result.insertRow();​ result.insertRow();​
 </​code>​ </​code>​
Line 370: Line 376:
  
 <code java> <code java>
-Statement statement = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,​ +Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,​ 
-                                                   ​ResultSet.CONCUR_UPDATABLE);​  +                                                 ​ResultSet.CONCUR_UPDATABLE);​  
-ResultSet result = statement.executeQuery("​SELECT issue_date, state FROM invoice");+ResultSet result = statement.executeQuery("​SELECT issue_date, state FROM invoice_header");
 GregorianCalendar today = new GregorianCalendar();​ GregorianCalendar today = new GregorianCalendar();​
 today.setTime(new Date()); today.setTime(new Date());
 while (result.next()) { while (result.next()) {
-    ​GregorianCalendar issueDate = result.getDate(issue_date);​ +  ​GregorianCalendar issueDate = result.getDate(issue_date);​ 
-    if (issueDate.before(today)) +  if (issueDate.before(today)) ​{ 
-        result.updateString(state,'​overdue'​);​ +    result.updateString(state,​ '​overdue'​);​ 
-    updateRow();​+  } 
 +  ​updateRow();​
 }  } 
 </​code>​ </​code>​
Line 396: Line 403:
  
 <code java> <code java>
-String query = "​UPDATE user SET type = ? WHERE role = ? ";+String query = "​UPDATE user SET type = ? WHERE personal_identifier ​= ?";
 PreparedStatement preparedStatement = dbConnection.prepareStatement(query);​ PreparedStatement preparedStatement = dbConnection.prepareStatement(query);​
 </​code>​ </​code>​
Line 404: Line 411:
 <code java> <code java>
 preparedStatement.setString(1,​ Integer.parseInt(buffer.readLine());​ preparedStatement.setString(1,​ Integer.parseInt(buffer.readLine());​
-preparedStatement.setDate(2, ​Date.valueOf(buffer.readLine());​+preparedStatement.setDate(2,​ buffer.readLine());​
 </​code>​ </​code>​
  
Line 423: Line 430:
 <code java> <code java>
 String query = "{? = CALL calculate_invoice_value(?​)}";​ String query = "{? = CALL calculate_invoice_value(?​)}";​
-CallableStatement callableStatement = dbConnection.prepareCall(query);​+CallableStatement callableStatement = connection.prepareCall(query);​
 callableStatement.registerOutParameter(1,​ java.sql.Types.DECIMAL);​ callableStatement.registerOutParameter(1,​ java.sql.Types.DECIMAL);​
-callableStatement.setString(2,​buffer.readLine());​+callableStatement.setString(2,​ buffer.readLine());​
 callableStatement.execute();​ callableStatement.execute();​
 double result = callableStatement .getDouble(1);​ double result = callableStatement .getDouble(1);​
Line 436: Line 443:
  
 Execuţia rutinei se face cu metoda ''​execute()'',​ iar valorile întoarse sunt preluate indexat, prin metodele ''​get...()''​ corespunzătoare. Execuţia rutinei se face cu metoda ''​execute()'',​ iar valorile întoarse sunt preluate indexat, prin metodele ''​get...()''​ corespunzătoare.
 +
 ==== Lucrul cu Dicționarul de Date ==== ==== Lucrul cu Dicționarul de Date ====
  
Line 441: Line 449:
  
 <code java> <code java>
-DatabaseMetaData dbMetaData = dbConnection.getMetaData();​+DatabaseMetaData dbMetaData = connection.getMetaData();​
 </​code>​ </​code>​
  
Line 574: Line 582:
  
 Clasa ''​DatabaseMetaData''​ pune la dispoziţie şi alte metode pentru verificarea capabilităţilor pe care le are driver-ul Java Database Connectivity utilizat. Clasa ''​DatabaseMetaData''​ pune la dispoziţie şi alte metode pentru verificarea capabilităţilor pe care le are driver-ul Java Database Connectivity utilizat.
 +
 ==== Tratarea Excepțiilor ==== ==== Tratarea Excepțiilor ====
  
Line 582: Line 591:
 Throwable cause = exception.getCause();​ Throwable cause = exception.getCause();​
 while (cause != null) { while (cause != null) {
-    ​System.out.println("​Cauza: "​+cause);​ +  ​System.out.println("​Cause: " + cause); 
-    cause = cause.getClause();​+  cause = cause.getClause();​
 } }
 </​code>​ </​code>​
Line 595: Line 604:
  
 Cel mai frecvent avertisment este de tip ''​DataTruncation''​ ce indică faptul că tipul de date folosit pentru obţinerea unui rezultat nu este cel corespunzător. Un astfel de obiect oferă posibilitatea investigării coloanei asupra căreia s-a produs eroarea, dacă aceasta corespunde unei operaţii de scriere sau de citire, câţi octeţi ar fi trebuit transferaţi şi câţi au fost transferaţi efectiv. Cel mai frecvent avertisment este de tip ''​DataTruncation''​ ce indică faptul că tipul de date folosit pentru obţinerea unui rezultat nu este cel corespunzător. Un astfel de obiect oferă posibilitatea investigării coloanei asupra căreia s-a produs eroarea, dacă aceasta corespunde unei operaţii de scriere sau de citire, câţi octeţi ar fi trebuit transferaţi şi câţi au fost transferaţi efectiv.
 +
 ==== Gestiunea Tranzacțiilor ==== ==== Gestiunea Tranzacțiilor ====
  
Line 614: Line 624:
  
 <code java> <code java>
-dbConnection.setAutoCommit(false);​ +connection.setAutoCommit(false);​ 
-Statement statement = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,​ +Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,​ 
-                                                   ​ResultSet.CONCUR_UPDATABLE);​  +                                                 ​ResultSet.CONCUR_UPDATABLE);​  
-for (ArrayList<​String>​ row:table) { +for (ArrayList<​String>​ row: table) { 
-    ​String ​query = "​INSERT INTO book VALUES ("; +  ​StringBuilder ​query = new StringBuilder("​INSERT INTO book VALUES ("); 
-    for(String column: row) +  for(String column: row) { 
-        query += column+",";​ +    query.append(column + ","​); 
-    query+= "​)";​ +  } 
-    ​dbConnection.addBatch(query);​+  ​query.append("​)"​); 
 +  ​connection.addBatch(query.toString());
 } }
 int[] result = statement.executeBatch();​ int[] result = statement.executeBatch();​
-dbConnection.commit();​ +connection.commit();​ 
-dbConnection.setAutoCommit(true);​+connection.setAutoCommit(true);​
 </​code>​ </​code>​
  
Line 654: Line 665:
 SavePoint state = dbConnection.setSavePoint();​ SavePoint state = dbConnection.setSavePoint();​
 ... ...
-dbConnection.rollback(state);​+connection.rollback(state);​
 </​code>​ </​code>​
  
Line 660: Line 671:
  
 O stare a bazei de date salvată poate fi eliminată din cadrul tranzacţiei folosind metoda ''​releaseSavePoint()''​ a obiectului de tip ''​Connection''​ corespunzător. O stare a bazei de date salvată poate fi eliminată din cadrul tranzacţiei folosind metoda ''​releaseSavePoint()''​ a obiectului de tip ''​Connection''​ corespunzător.
 +
 ==== Alternative la Manipularea Informațiilor din Baza de Date ==== ==== Alternative la Manipularea Informațiilor din Baza de Date ====
  
Line 679: Line 691:
  
   - <code java>   - <code java>
-Statement statement = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,​ +Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,​ 
-                                                   ​ResultSet.CONCUR_UPDATABLE);​+                                                 ​ResultSet.CONCUR_UPDATABLE);​
 ResultSet result = statement.executeQuery("​SELECT * FROM book"​);​ ResultSet result = statement.executeQuery("​SELECT * FROM book"​);​
 JdbcRowSet jdbcRowSet = new JdbcRowSetImpl(result);​ JdbcRowSet jdbcRowSet = new JdbcRowSetImpl(result);​
Line 690: Line 702:
 </​code>​ Obiectul de tip ''​JdbcRowSet''​ nu conţine nici un fel de date până la momentul când nu îi este asociată o instrucţiune SQL prin metoda ''​setCommand'',​ apelată prin metoda ''​execute()''​. Implicit, un astfel de obiect poate fi parcurs, iar informaţiile din el pot fi actualizate. Astfel de comportamente pot fi specificate însă şi explicit.\\ Metoda ''​execute()''​ realizează conexiunea cu baza de date folosind parametrii conexiunii respective, execută interogarea aferentă proprietăţii ''​command''​ și gestionează stochează informaţiile din obiectul ''​ResultSet''​ reţinut în obiectul de tip ''​JdbcRowSet''​. </​code>​ Obiectul de tip ''​JdbcRowSet''​ nu conţine nici un fel de date până la momentul când nu îi este asociată o instrucţiune SQL prin metoda ''​setCommand'',​ apelată prin metoda ''​execute()''​. Implicit, un astfel de obiect poate fi parcurs, iar informaţiile din el pot fi actualizate. Astfel de comportamente pot fi specificate însă şi explicit.\\ Metoda ''​execute()''​ realizează conexiunea cu baza de date folosind parametrii conexiunii respective, execută interogarea aferentă proprietăţii ''​command''​ și gestionează stochează informaţiile din obiectul ''​ResultSet''​ reţinut în obiectul de tip ''​JdbcRowSet''​.
   - <code java>   - <code java>
-JdbcRowSet ​jdbcRS ​= new JdbcRowSetImpl();​ +JdbcRowSet ​jdbcRowSet ​= new JdbcRowSetImpl();​ 
-jdbcRS.setURL("​jdbc:​mysql://​localhost:​3306/​bookstore"​);​ +jdbcRowSet.setURL("​jdbc:​mysql://​localhost:​3306/​bookstore"​);​ 
-jdbcRS.setUsername(username);​ +jdbcRowSet.setUsername(username);​ 
-jdbcRS.setPassword(password);​ +jdbcRowSet.setPassword(password);​ 
-jdbcRS.setCommand("​SELECT * FROM book"​);​ +jdbcRowSet.setCommand("​SELECT * FROM book"​);​ 
-jdbcRS.execute();+jdbcRowSet.execute();
 </​code>​ Pentru fiecare obiect ''​JdbcRowSet''​ se pot stabili proprietăţile (''​url'',​ ''​username'',​ ''​password'',​ ''​dataSourceName''​). O interogare se poate specifica folosind metoda ''​setCommand()'',​ iar execuţia se face folosind ''​execute()'',​ ca şi în cazul ''​ResultSet''​. ​ </​code>​ Pentru fiecare obiect ''​JdbcRowSet''​ se pot stabili proprietăţile (''​url'',​ ''​username'',​ ''​password'',​ ''​dataSourceName''​). O interogare se poate specifica folosind metoda ''​setCommand()'',​ iar execuţia se face folosind ''​execute()'',​ ca şi în cazul ''​ResultSet''​. ​
   - <code java>   - <code java>
Line 739: Line 751:
 <code java> <code java>
 try { try {
-    ​cachedRowSet.acceptChanges();​+  ​cachedRowSet.acceptChanges();​
 } catch (SyncProviderException syncProviderException ) { } catch (SyncProviderException syncProviderException ) {
-    ​SyncResolver syncResolver = syncProviderException.getSyncResolver();​ +  ​SyncResolver syncResolver = syncProviderException.getSyncResolver();​ 
-    while (syncResolver .nextConflict()) { +  while (syncResolver .nextConflict()) { 
-        if (syncResolver.getStatus() == SyncResolver.UPDATE_ROW_CONFLICT) { +    if (syncResolver.getStatus() == SyncResolver.UPDATE_ROW_CONFLICT) { 
-            int conflictedRow = syncResolver.getRow();​ +      int conflictedRow = syncResolver.getRow();​ 
-            cachedRowSet.absolute(conflictedRow);​ +      cachedRowSet.absolute(conflictedRow);​ 
-            int numberOfAttributes = cachedRowSet.getMetaData().getColumnCount();​ +      int numberOfAttributes = cachedRowSet.getMetaData().getColumnCount();​ 
-            for (int index = 1; index <= numberOfAttributes;​ index++) { +      for (int index = 1; index <= numberOfAttributes;​ index++) { 
-                if (syncResolver.getConflictValue(index) != null) { +        if (syncResolver.getConflictValue(index) != null) { 
-                    Object cachedRowSetValue = cachedRowSet.getObject(index);​ +          Object cachedRowSetValue = cachedRowSet.getObject(index);​ 
-                    Object resolverValue = syncResolver.getConflictValue(index);​ +          Object resolverValue = syncResolver.getConflictValue(index);​ 
-                    // ... +          // ... 
-                    syncResolver.setResolvedValue(index,​...);​ +          syncResolver.setResolvedValue(index,​...);​ 
-                } +        } 
-             ​} +      } 
-         ​} +    } 
-     ​}+  }
 } }
 </​code>​ </​code>​
Line 780: Line 792:
 public class PriceFilter implements Predicate { public class PriceFilter implements Predicate {
  
-    ​private int lowValue, highValue;​ +  ​private int lowValue, highValue;​ 
-    private String attributeName = null; +  private String attributeName = null; 
-    private int attributeIndex = -1;+  private int attributeIndex = -1;
     ​     ​
-    ​public PriceFilter(int lowValue, int highValue, String attributeName) { +  ​public PriceFilter(int lowValue, int highValue, String attributeName) { 
-        this.lowValue = lowValue; +    this.lowValue = lowValue; 
-        this.highValue = highValue;​ +    this.highValue = highValue;​ 
-        this.attributeName = attributeName;​+    this.attributeName = attributeName; 
 +  } 
 + 
 +  public PriceFilter(int lowValue, int highValue, int attributeIndex) { 
 +    this.lowValue = lowValue; 
 +    this.highValue = highValue;​ 
 +    this.attributeIndex = attributeIndex;​ 
 +  } 
 + 
 +  public boolean evaluate(Object value, String attributeName) { 
 +    boolean result = true; 
 +    if (attributeName.equalsIgnoreCase(this.attributeName)) { 
 +      int attributeValue = ((Integer)value).intValue();​ 
 +      if (attributeValue >= this.lowValue && attributeValue <= this.highValue) { 
 +        return true; 
 +      } 
 +      return false;
     }     }
-    public ​PriceFilter(int lowValue, int highValue, int attributeIndex) { +    ​return result; 
-        ​this.lowValue ​= lowValue; +  } 
-        this.highValue ​= highValue; + 
-        this.attributeIndex ​= attributeIndex;+  ​public ​boolean evaluate(Object value, int attributeIndex) { 
 +    ​boolean result ​= true; 
 +    if (attributeIndex == this.attributeIndex)) { 
 +      int attributeValue ​= ((Integer)value).intValue(); 
 +      if (attributeValue >= this.lowValue && attributeValue <= this.highValue) { 
 +        return true; 
 +      } 
 +      return false;
     }     }
-    public boolean evaluate(Object value, String attributeName) { +    ​return result; 
-        boolean result = true; +  } 
-        ​if ​(attributeName.equalsIgnoreCase(this.attributeName)) { + 
-            int attributeValue = ((Integer)value).intValue(); +  ​public boolean evaluate (RowSet rowSet) { 
-            if (attributeValue >= this.lowValue && ​attributeValue ​<= this.highValue) +    boolean result = false; 
-                return true; +    ​CachedRowSet cachedRowSet = (CachedRowSet)rowSet; 
-            return false; +    int attributeValue = -1; 
-        } +    if (this.attributeName != null) { 
-        return result; +      ​attributeValue = cachedRowSet.getInt(this.attributeName); 
-    } +    } else if (this.attributeIndex ​> 0)) { 
-    public boolean evaluate(Object value, int attributeIndex) { +      attributeValue = cachedRowSet.getInt(this.attributeIndex); 
-        boolean result = true; +    } else { 
-        ​if (attributeIndex == this.attributeIndex)) { +      return ​false;
-            ​int ​attributeValue = ((Integer)value).intValue(); +
-            if (attributeValue >= this.lowValue && attributeValue <= this.highValue) +
-                return true; +
-            ​return false; +
-        ​} +
-        return ​result;+
     }     }
-    ​public boolean evaluate (RowSet rowSet) { +    if (attributeValue >= this.lowValue && attributeValue <= this.highValue) ​{ 
-        boolean result = false; +      result = true;
-        CachedRowSet cachedRowSet = (CachedRowSet)rowSet;​ +
-        int attributeValue = -1; +
-        if (this.attributeName != null) +
-            attributeValue = cachedRowSet.getInt(this.attributeName);​ +
-        else if (this.attributeIndex > 0)) +
-            attributeValue = cachedRowSet.getInt(this.attributeIndex);​ +
-        else +
-            return false; +
-        ​if (attributeValue >= this.lowValue && attributeValue <= this.highValue) +
-            result = true; +
-        return result;+
     }     }
 +    return result;
 +  }
 } }
 </​file>​ </​file>​
Line 842: Line 862:
  
 <code java> <code java>
-CachedRowSet ​invoices ​= new CachedRowSetImpl();​ +CachedRowSet ​invoice_headers ​= new CachedRowSetImpl();​ 
-invoices.setURL("​jdbc:​mysql://​localhost:​3306/​bookstore"​);​ +invoice_headers.setURL("​jdbc:​mysql://​localhost:​3306/​bookstore"​);​ 
-invoices.setUsername(username);​ +invoice_headers.setUsername(username);​ 
-invoices.setPassword(password);​ +invoice_headers.setPassword(password);​ 
-invoices.setCommand("​SELECT * FROM invoice"); +invoice_headers.setCommand("​SELECT * FROM invoice_header"); 
-invoices.setMatchColumn("​id"​);​ +invoice_headers.setMatchColumn("​id"​);​ 
-invoices.execute();​ +invoice_headers.execute();​ 
-CachedRowSet ​invoices_details ​= new CachedRowSetImpl();​ +CachedRowSet ​invoice_lines ​= new CachedRowSetImpl();​ 
-invoices_details.setURL("​jdbc:​mysql://​localhost:​3306/​bookstore"​);​ +invoice_lines.setURL("​jdbc:​mysql://​localhost:​3306/​bookstore"​);​ 
-invoices_details.setUsername(username);​ +invoice_lines.setUsername(username);​ 
-invoices_details.setPassword(password);​ +invoice_lines.setPassword(password);​ 
-invoices_details.setCommand("​SELECT * FROM invoice_detail"); +invoice_lines.setCommand("​SELECT * FROM invoice_line"); 
-invoices_details.setMatchColumn("​invoice_id"); +invoice_lines.setMatchColumn("​invoice_header_id"); 
-invoices_details.execute();+invoice_lines.execute();
 JoinRowSet joinRowSet = new JoinRowSetImpl();​ JoinRowSet joinRowSet = new JoinRowSetImpl();​
-joinRowSet.addRowSet(invoices); +joinRowSet.addRowSet(invoice_headers); 
-joinRowSet.addRowSet(invoices_details);+joinRowSet.addRowSet(invoice_lines);
 </​code>​ </​code>​
  
Line 870: Line 890:
  
 <code java> <code java>
-java.io.FileOutputStream fileOutputStream = new java.io.FileOutputStream("​genres.xml"​);​ +java.io.FileOutputStream fileOutputStream = new java.io.FileOutputStream("​category.xml"​);​ 
-genres.writeXml(fileOutputStream);​+categories.writeXml(fileOutputStream);​
 </​code>​ </​code>​
  
 <code java> <code java>
-java.io.FileWriter fileWriter = new java.io.FileWriter("​genres.xml"​);​ +java.io.FileWriter fileWriter = new java.io.FileWriter("​category.xml"​);​ 
-genres.writeXml(fileWriter);​+categories.writeXml(fileWriter);​
 </​code>​ </​code>​
  
Line 882: Line 902:
  
 <code java> <code java>
-genres.writeXml(resultSet,​ fileOutputStream);​ +categories.writeXml(resultSet,​ fileOutputStream);​ 
-genres.writeXml(resultSet,​ fileWriter);​+categories.writeXml(resultSet,​ fileWriter);​
 </​code>​ </​code>​
  
Line 889: Line 909:
  
 <code java> <code java>
-java.io.FileInputStream fileInputStream = new java.io.FileOutputStream("​genres.xml"​);​ +java.io.FileInputStream fileInputStream = new java.io.FileOutputStream("​category.xml"​);​ 
-genres.readXml(fileOutputStream);​+categories.readXml(fileOutputStream);​
 </​code>​ </​code>​
  
 <code java> <code java>
-java.io.FileReader fileReader = new java.io.FileReader("​genres.xml"​);​ +java.io.FileReader fileReader = new java.io.FileReader("​category.xml"​);​ 
-genres.readXml(fileReader);​+categories.readXml(fileReader);​
 </​code>​ </​code>​
  
Line 914: Line 934:
  
 Se doreşte proiectarea unei aplicaţii care exploatează o bază de date ce urmează să fie integrată în cadrul unui sistem ERP pentru o librărie care comercializează cărţi. Se va porni de la schema conceptuală,​ respectiv de la structura bazei de date construite în cadrul laboratorului anterior. Se doreşte proiectarea unei aplicaţii care exploatează o bază de date ce urmează să fie integrată în cadrul unui sistem ERP pentru o librărie care comercializează cărţi. Se va porni de la schema conceptuală,​ respectiv de la structura bazei de date construite în cadrul laboratorului anterior.
 +
 +Proiectul poate fi dezvoltat folosind [[https://​maven.apache.org/​|Apache Maven]], fiind necesar să se precizeze configurațiile de rulare în mediile integrate de dezvoltare, în acest scop.
 +
 +==== Eclipse Mars (4.5) ====
 +
 +Pentru acțiunea //Run As// → //Maven Build// disponibilă în meniul contextual al proiectului (click dreapta în secțiunea //Package Explorer//​),​ se poate defini o configurație de rulare care va realiza simultan acțiunile de curățare a fișierelor generate, compilare și testare.
 +
 +{{ :​laboratoare:​laborator01:​04eclipse_project_configuration06.png?​nolink }}
 +
 +O configurație de rulare este caracterizată prin următoarele caracteristici (în panoul de prezentare //Main//):
 +  * denumire (//eng.// Name);
 +  * locație (//eng.// Base directory) - de regulă, referința se face relativ la spațiul de lucru, disponibil la ''​${workspace_loc:​}'';​
 +  * acțiunile care vor fi realizate (//eng.// Goals): pot fi specificate acțiuni precum ''​clean'',​ ''​build'',​ ''​compile'',​ ''​install''​ sau ''​test'',​ dacă este necesar);
 +  * diferiți parametri (definiți prin nume și valoare), în situația în care este necesar un control mai exact al comportamentului,​ în detrimentul celui implicit.
 +
 +{{ :​laboratoare:​laborator01:​04eclipse_project_configuration07.png?​nolink }}
 +
 +==== NetBeans 8.0.2 ====
 +
 +O configurație de rulare trebuie specificată în secțiunea //​Configurations//​ din meniul contextual al proiectului (disponibil prin acțiunea click dreapta pe denumirea proiectului în panoul de prezentare //​Projects//​). Crearea unei configurații de rulare noi se face prin accesarea butonului //Add...//.
 +
 +{{ :​laboratoare:​laborator01:​05netbeans_project_configuration04.png?​nolink }}
 +
 +Pentru fiecare configurație de rulare trebuie specificată o denumire unică (//​Configuration Id//). Pentru ca proiectul să poată fi utilizat și pe alte platforme este necesar să NU fie selectată opțiunea //Keep private to this IDE instance//.
 +
 +{{ :​laboratoare:​laborator01:​05netbeans_project_configuration05.png?​nolink }}
 +
 +Este necesar să se indice scopurile asociate pentru fiecare acțiune corespunzătoare configurației de rulare, existând posibilitatea de a se preciza suplimentar și o serie de proprietăți.
 +
 +<note tip>​Sintaxa utilizată pentru o proprietate este ''​-D<​property_name>​=<​property_value>''​.</​note> ​
 +
 +{{ :​laboratoare:​laborator01:​05netbeans_project_configuration06.png?​nolink }}
 +
 +Accesarea unei acțiuni a proiectului se face din meniul contextual al acestuia, executându-se,​ de fiecare dată, scopurile care au fost specificate anterior.
 +
 +{{ :​laboratoare:​laborator01:​05netbeans_project_configuration07.png?​nolink }}
 +
 +===== =====
  
 **0**. Să se cloneze în directorul de pe discul local conținutul depozitului la distanță de la [[https://​www.github.com/​aipi2015/​Laborator01|]]. În urma acestei operații, directorul ''​Laborator01''​ va trebui să conțină subdirectorul ''​labtasks'',​ fișierele ''​README.md''​ și ''​LICENSE''​. <​code>​ **0**. Să se cloneze în directorul de pe discul local conținutul depozitului la distanță de la [[https://​www.github.com/​aipi2015/​Laborator01|]]. În urma acestei operații, directorul ''​Laborator01''​ va trebui să conțină subdirectorul ''​labtasks'',​ fișierele ''​README.md''​ și ''​LICENSE''​. <​code>​
Line 921: Line 979:
 <note tip>În interfața ''​Constants''​ din pachetul ''​ro.pub.cs.aipi.lab01.general'',​ trebuie să se modifice valoarea constantei ''​DATABASE_PASSWORD''​ care stochează parola de conectare pentru utilizatorul ''​root''​ la sistemul de gestiune al bazei de date.</​note>​ <note tip>În interfața ''​Constants''​ din pachetul ''​ro.pub.cs.aipi.lab01.general'',​ trebuie să se modifice valoarea constantei ''​DATABASE_PASSWORD''​ care stochează parola de conectare pentru utilizatorul ''​root''​ la sistemul de gestiune al bazei de date.</​note>​
  
-<note important>​Proiectul este organizat sub forma unei suite de teste unitare, corespunzătoare fiecărui exercițiu în parte. În principiu, fiecare test unitar este independent,​ însă având în vedere faptul că unele dintre acestea modifică starea bazei de date, este recomandat ca exercițiile să fie rezolvate în ordine. Pentru ca rezultatul testelor să fie același, structura și conținutul bazei de date sunt recreate de fiecare dată, curățându-se și rezultatul rulărilor anterioare (această operație poate dura o perioadă de timp mai îndelungată,​ în funcție de performanțele mașinii pe care se rulează). În directorul ''​input''​ sunt plasate fișierele de referință cu care se face comparația pentru rezultatul fiecărui test unitar.</​note>​+Proiectul este organizat sub forma unei suite de teste unitare, corespunzătoare fiecărui exercițiu în parte. În principiu, fiecare test unitar este independent,​ însă având în vedere faptul că unele dintre acestea modifică starea bazei de date, este recomandat ca exercițiile să fie rezolvate în ordine. ​ 
 + 
 +Pentru ca rezultatul testelor să fie același, structura și conținutul bazei de date sunt recreate de fiecare dată, curățându-se și rezultatul rulărilor anterioare (această operație poate dura o perioadă de timp mai îndelungată,​ în funcție de performanțele mașinii pe care se rulează). ​ 
 + 
 +În directorul ''​input''​ sunt plasate fișierele de referință cu care se face comparația pentru rezultatul fiecărui test unitar. ​În directorul ''​output''​ sunt plasate fișierele rezultate în urma rulării testelor unitare.  
 + 
 +<note important>​ 
 +În situația în care proiectul este rulat folosind utilitarul Maven, este necesar ca pentru scopul ''​test''​ să se specifice proprietatea ''​-Dtest=ro.pub.cs.lab01.main.AllTests'',​ pentru a se forța rularea suitei de teste unitare în detrimentul rulării fiecărui test unitar în parte. Aceasta asigură faptul că testele unitare vor fi executate în ordine, precum și realizarea operațiilor de încărcare / descărcare a bazei de date înainte de fiecare rulare. 
 +</​note>​
  
 **1**. Să se implementeze metoda ''​getTableNumberOfRows()''​ din clasa ''​DatabaseOperationsImplementation''​ a pachetului ''​ro.pub.cs.aipi.lab01.dataaccess'',​ ce determină numărul de înregistrări al unei tabele identificată prin denumire (transmisa ca parametru). <code java> **1**. Să se implementeze metoda ''​getTableNumberOfRows()''​ din clasa ''​DatabaseOperationsImplementation''​ a pachetului ''​ro.pub.cs.aipi.lab01.dataaccess'',​ ce determină numărul de înregistrări al unei tabele identificată prin denumire (transmisa ca parametru). <code java>
Line 1049: Line 1115:
  
 <​spoiler|Indicații de Rezolvare>​ <​spoiler|Indicații de Rezolvare>​
-Filtrarea se aplică pe rezultatul obținut. Se poate utiliza un obiect de tipul ''​PriceFilter''​ din pachetul ''​ro.pub.cs.aipi.lab01.helper'',​ ca parametru al metodei ''​setFilter()''​.+Filtrarea se aplică pe rezultatul obținut ​(după ce anterior au fost realizate operațiile de asociere dintre tabele). Se poate utiliza un obiect de tipul ''​PriceFilter''​ din pachetul ''​ro.pub.cs.aipi.lab01.helper'',​ ca parametru al metodei ''​setFilter()''​.
 </​spoiler>​ </​spoiler>​
  
Line 1080: Line 1146:
 ===== Soluții ===== ===== Soluții =====
  
-TODO+[[https://​github.com/​aipi2015/​Laborator01/​tree/​master/​solutions/​eclipse/​01-BookStore-JDBC|Proiect Eclipse]]\\  
 +[[https://​github.com/​aipi2015/​Laborator01/​tree/​master/​solutions/​netbeans/​01-BookStore-JDBC|Proiect NetBeans]]
laboratoare/laborator01.1445183925.txt.gz · Last modified: 2015/10/18 18:58 by Andrei Roșu-Cojocaru
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0