[email protected] Laborator 10 Fişiere Citire fişier import java.io.*; class MyFileRead { public static void main(String args[]){ try{ //se deschide fisierul FileInputStream fstream = new FileInputStream("textfile.txt"); // se preia obiectul DataInputStream in = new DataInputStream(fstream); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String strLine; //se citeste linie de linie din fisier while ((strLine = br.readLine()) != null) { // se printeaza continutul System.out.println (strLine); } //se inchide fluxul de intrare in.close(); }catch (Exception e){ System.err.println("Error: " + e.getMessage()); } } }
Scriere fişier import java.io.*; class MyFile { public static void main(String args[]){ try{ // creeaza fisierul FileWriter fstream = new FileWriter("out.txt"); BufferedWriter out = new BufferedWriter(fstream); out.write("Hello Java"); //inchide fisierul out.close(); }catch (Exception e){ System.err.println("Error: " + e.getMessage()); } } }
Baze de date Java poate accesa mai multe tipuri de baze de date (de la un simplu fişier text, până la un obiecte de tip baza de date). Ȋn majoritatea aplicaţiilor se scrie o clasa numită accesor, care face legătura dintre baza de date şi restul aplicaţiei. De exemplu, dacă folosim JDBC, răspunsurile query-urilor se ȋntorc sub forma unui obiect de tip ResultSet.
1
[email protected]
Exemplu. Să presupunem că avem o aplicaţie de tip Sistem de Management al Datelor cu Caracter Personal. Avem clasele primare: Persoană, Adresă şi Ȋntâlnire. Ar fi indicat să scriem o clasă PersoanăAccesor pentru a prelua numele şi adresele din baza de date (probabil folosind JDBC) şi să generăm obiecte Persoană şi Adresă din ea. Obiectele din clasa accesor sunt actualizate, iar actualizările respective trebuie să se reflecte şi ȋn baza de date. Java DataBase Connectivity (JDBC) are clase incluse ȋn pachetul java.sql şi extensiile JDBC Level 2 ȋn pachetul javax.sql. Reţeta nr 1: Setarea şi Conectarea la JDBC Problemă. Vrem să accesăm o bază de date via JDBC. Soluţie. Folosim Class.forName() şi DriverManager.getConnection(). Discuţie. Recapitulare. • SQL are query-uri de forma: “SELECT * from userdb”. • SQL face update-urile folosind: INSERT, DELETE, CREATE şi DROP. JDBC are două niveluri: JDBC1 şi JDBC2. Nivelul 1 este inclus ȋn implementarea şi driverele JDBC, Nivelul 2 este opţional şi are nevoie de un driver Level 2. Noi vom lucra cu Nivelul 1. Folosirea unui query JDBC pas cu pas Cum se creează un JDBC query: 1. Se ȋncarcă clasa potrivită Driver, fapt ce are ca efect secundar ȋnregistrarea cu DriveManager-ul. 2. Se creează un obiect Connection, folosind metoda DriverManager.getConnection(): Connection con = DriverManager.getConnection (dbURL, name, pass);
3. Se creează un obiect Statement, folosind metoda obiectului Connection, createStatement(): Statement stmt = con.createStatement( );
4. Se creează un obiect ResultSet, folosind metoda obiectului Statement executQuery(): ResultSet rs = stmt.executeQuery("select * from MyTable");
5. Se iterează ResultSet-ul:
2
[email protected] while (rs.next( )) { int x = rs.getInt("CustNO");
6. Se ȋnchide ResultSet. 7. Se ȋnchide Statement. 8. Se ȋnchide Connection. Reţeta nr 2: Conectarea la o baza de date JDBC Problemă. Vrem să ne conectăm la o bază de date. Soluţie. Folosim DriverManager.getConnection(). Discuţie. Metoda de clasă DriverManager.getConnection() permite conectarea la o baza de date folosind un URL de genul: jdbc:dbmsnetproto://server:4567/mydatabase, un nume de logare şi o parolă. Drivere JDBC
sun.jdbc.odbc.JdbcOdb cDriver
Clasa Driver-ului jdbc:odbc:
dbURL
Baza de date Microsoft ODBC (Inclus ȋn JDK)
jdbc.idbDriver
jdbc:idb:
Instant Database (IDB)
oracle.jdbc.Driver.Or acleDriver
jdbc:oracle:thin:@server:port #:dbname
Oracle
postgresql.Driver
jdbc:postgres://host/database
PostGreSQL (free) http://www.postgresql.org)
org.gjt.mm.mysql.Driv er
jdbc:mysql://host/database
MySql (free http://www.mysql.com)
import java.awt.*; import java.sql.*; /** Se incarca un driver si ne conectam la baza de date * */ public class Connect {
3
[email protected] public static void main(String[] av) { String dbURL = "jdbc:odbc:WRBC"; try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); DriverManager.setLogStream(System.err); System.out.println("Getting Connection"); Connection conn = DriverManager.getConnection(dbURL, "ian", ""); // utilizator, parola //Daca un obiect SQLWarning e valabil il afiseaza SQLWarning warn = conn.getWarnings( ); while (warn != null) { System.out.println("SQLState: " + warn.getSQLState( )); System.out.println("Message: " + warn.getMessage( )); System.out.println("Vendor: " + warn.getErrorCode( )); System.out.println(""); warn = warn.getNextWarning( ); } //Procesarea conexiunii conn.close( ); } catch (ClassNotFoundException e) { System.out.println("Nu pot incarca driver-ul " + e); } catch (SQLException e) { System.out.println("Nu pot accesa baza de date " + e); } } }
Reţeta nr 3. Trimiterea unui query JDBC şi obţinerea rezultatelor Soluţie. Creează un obiect Statement şi foloseşte-l pentru a executa un query. Rezultatul ȋl pui ȋntr-un obiect de tip ResultSet. Discuţie. Obiectul Connetion poate să genereze mai multe tipuri de statements. Cel mai simplu este un Statement creat de createStatement(), care este folosit pentru a trimite un query SQL ca string: Statement stmt = conn.createStatement( ); stmt.executeQuery("select * from myTable");
Rezultatul query-ului este returnat ȋntr-un obiect de tip ResultSet. ResultSet-ul lucrează ca un iterator, adică permite accesarea liniilor din rezultatul query-ului. while (rs.next( )) { int i = rs.getInt(1);
// sau getInt("UserID");
După cum se vede din comentariu, se pot obţine elemente din ResultSet prin indexul coloanei (care porneste de la 1, ȋn ciuda faptului că ȋn Java se porneşte de la zero) sau prin numele coloanei. String bar, beer ;
4
[email protected] float price ; ResultSet rs = stmt.executeQuery("SELECT * FROM Sells"); while ( rs.next() ) { bar = rs.getString("bar"); beer = rs.getString("beer"); price = rs.getFloat("price"); System.out.println(bar + " sells " + beer + " for " + price + " Dollars."); } Sau… bar = rs.getString(1); price = rs.getFloat(3); beer = rs.getString(2);
Tranzacţii JDBC-ul permite comenzilor SQL să fie grupate ȋntr-o singură tranzacţie. Astfel putem asigura ACID (Atomcity, Consistency, Isolation, Durability). Controlul tranzacţiilor se face prin obiectul Connection. Când se creează o conexiune, ea este ȋn modul auto-commit. Acest lucru ȋnseamnă că fiecare comandă SQL este tratată ca şi tranzacţie şi i se va aplica commit ȋn momentul ȋn care execuţia a luat sfârşit. Putem să oprim modul auto-commit pentru o conexiune activă cu : con.setAutoCommit(false);
şi pentru a-l porni din nou: con.setAutoCommit(true) ;
Odată ce este oprit auto-commit-ul, nicio comandă SQL nu o să fie committed (baza de date nu va fi permanent updatată), până ȋn momentul ȋn care acest lucru este cerut concret: con.commit() ;
Ȋn orice moment, ȋnainte de a face commit, putem să apelăm rollback() şi să anulăm tranzacţia. con.setAutoCommit(false); Statement stmt = con.createStatement(); stmt.executeUpdate("INSERT INTO Sells VALUES('Bar Of Foo', 'BudLite', 1.00)" ); con.rollback(); stmt.executeUpdate("INSERT INTO Sells VALUES('Bar Of Joe', 'Miller', 2.00)" ); con.commit(); con.setAutoCommit(true);
5
[email protected] Tratarea erorilor cu ajutorul Excepţiilor Ȋn programele care lucrează cu baze de date pot apărea multe erori, care trebuie reparate. Programele trebuie să recupereze datele pierdute ȋn urma erorilor şi să lase baza de date ȋntr-o stare corectă. Pentru a realiza acest lucru trebuie folosit rollback-ul. Clientul (programul) care accesează un server (baza de date) trebuie să fie prevenit de orice eroare care poate fi returnată de server. JDBC oferă accesul la astfel de informaţii prin: SQLExeption şi SQLWarning. SQLExceptions sunt excepţii Java, care dacă nu sunt tratate vor ȋnchide aplicaţia. SQLWarnings sunt subclase ale lui SQLException, dar reprezintă erori nefatale, care pot fi ignorate. Exemplu. Un exemplu de prindere a unei excepţii SQLException şi de folosire a rollback-ului pentru anularea tranzacţiei. try { con.setAutoCommit(false) ; stmt.executeUpdate("CREATE TABLE Sells (bar VARCHAR2(40), " + "beer VARHAR2(40), price REAL)") ; stmt.executeUpdate("INSERT INTO Sells VALUES " + "('Bar Of Foo', 'BudLite', 2.00)") ; con.commit() ; con.setAutoCommit(true) ; }catch(SQLException ex) { System.err.println("SQLException: " + ex.getMessage()) ; con.rollback() ; con.setAutoCommit(true) ; }
Ȋn acest caz, o excepţie este aruncată, deoarece beer este definită ca şi VARHAR2, deci greşit. SQLWarnings pot să returneze obiecte de tip Connection, obiecte Statement, obiecte ResultSet. ResultSet rs = stmt.executeQuery("SELECT bar FROM Sells") ; SQLWarning warn = stmt.getWarnings() ; if (warn != null) System.out.println("Message: " + warn.getMessage()) ; SQLWarning warning = rs.getWarnings() ; if (warning != null) warning = warning.getNextWarning() ; if (warning != null) System.out.println("Message: " + warn.getMessage()) ;
6