Documente Academic
Documente Profesional
Documente Cultură
JDBC
JDBC (Java DataBase Connectivity) este o parte a Java API dedicat conectrii la baze de date. Utiliznd JDBC, putem executa instruciuni/comenzi SQL pentru orice baz de date relaional. Etapele principale ntr-o aplicaie ce folosete JDBC sunt urmtoarele: - deschiderea unei conexiuni ctre baza de date; - crearea unui "obiect instruciune" prin care transmitem instruciuni SQL ctre gestionarul bazei de date; - regsirea rezultatelor. Principalele clase i interfee se gsesc n pachetul java.sql. Dintre acestea vom prezenta doar urmtoarele interfee:
public interface Connection public interface Statement
stabilete conexiunea la baza de date; creaz un "obiect instruciune"; acesta poate interoga baza de date prin invocarea de metode specializate pentru comenzile SQL, transmind ca argument un ir de caractere ce constituie o comand SQL valid; permite regsirea rezultatelor interogrii;
public interface PreparedStatement
permite lucrul cu instruciuni SQL cu parametri. Vom prezenta n continuare numai principalele aspecte legate de JDBC. Presupunem n continuare c cititorul este familiarizat cu forma comenzilor SQL i c baza de date este creat folosind Microsoft Access. De asemenea, presupunem pentru moment c baza de date este local.
deschid Microsoft Access Blank Access Database merg n directorul meu File Name: Agenda Create selectez: Create Table in Design view i Tables Open introduc numele cmpurilor + tipul lor nchid Salvez sub numele: Persoane fr cheie primar Click pe Persoane: pot introduce nregistrri
2
-
nchid toate ferestrele. Pentru exemplificare, plecm de la urmtorul coninut al tabelei Persoane:
Presupunem c numele sursei de date este AgendaODBC. Mergem succesiv n: Control Panel Administrative Tools Data Sources (ODBC) System DSN sau UserDSN (baza de date a sistemului sau a utilizatorului) Add selectez *.mdb Data Source Name: AgendaODBC Select merg n directorul meu selectez Agenda.mdb OK OK nchid. ncrcarea driver-ului ODBC se realizeaz prin:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Se observ c trebuie trimis numele utilizatorului i o parol, pentru o eventual validare a accesului la baza de date.
obiect este posibil executarea de instruciuni SQL, cu primirea rezultatelor cutrii. n continuare trebuie creat un ir de caractere care s reprezinte o comand SQL valid:
String sql = "...";
Urmeaz transmiterea cererii i obinerea rezultatului interogrii folosind una dintre metodele:
public ResultSet executeQuery(String sql) throws SQLException unde sql reprezint o instruciune SQL de tip SELECT. Este ntors un obiect de tipul ResultSet care permite regsirea rezultatelor cererii; public int executeUpdate(String sql) throws SQLException unde sql reprezint o instruciune SQL de unul dintre tipurile INSERT,
UPDATE, sau DELETE. Este ntors numrul liniei (nregistrrii) afectate. Interfaa:
public interface ResultSet
permite regsirea, sub forma unui tabel, a rezultatelor cutrii la executarea unei metode executeQuery. Un obiect de acest tip menine un cursor la linia curent din tabel, iniial la prima linie a acestuia. Dintre metodele interfeei ResultSet prezentm deocamdat numai urmtoarele:
public boolean next() ntoarce true dac i numai dac mai exist linii n rs, caz n care se trece la
urmtoarea nregistrare;
4
public gettip(String s)
ntoarce coninutul cmpului cu numele s din nregistrarea curent ca o valoare de tipul tip din Java; tip poate fi String, Int etc. Observaie. Obiectele con i stmt trebuie "nchise" n final prin invocarea metodei close().
Exemplu
nregistrrile (liniile) din baza de date cu care lucrm corespund informaiilor despre o persoan i au cmpurile Nume, Prenume, Localitate i Salariu, cu semnificaii evidente. Corespunztor, scriem clasa Persoana n care constructorul iniializeaz cmpurile, iar metodele ntorc valorile lor.
import java.io.*; class Persoana implements Serializable { private String nume,prenume,localitate; private int salariu; public Persoana(String n, String p, String l, int s) { nume = n; prenume = p; localitate = l; salariu = s; } public String rNume() { return nume; } public String rPrenume() { return prenume; } public String rLocalitate() { return localitate; } public int rSalariu() { return salariu; } public String toString() { return nume + "\t" + prenume + "\t" + localitate + "\t" + salariu; } }
unde implementarea interfeei Serializable va fi util ulterior pentru transmiterea la distan a obiectelor de tipul Persoana. Asupra bazei de date vom executa doar dou operaii: selectarea tuturor nregistrrilor cu un nume i o localitate date: inserarea unei noi nregistrri:
SELECT * FROM PERSOANE WHERE NUME='...' AND LOCALITATE='...' pentru care vom folosi metoda executeQuery; INSERT INTO PERSOANE (NUME,PRENUME,LOCALITATE,SALARIU) VALUES('...','...','...','...') pentru care vom folosi metoda executeUpdate. Aceste operaii corespund metodelor cauta i adauga din clasa BD, clasa care are un cmp stmt de tipul Statement, care primete valoare prin constructor: import java.sql.*; class BD { Statement stmt; BD(Statement s) { stmt = s; } public void cauta(String nume,String loc) throws Exception { Persoana p = null;
5
String my_query = "SELECT * FROM PERSOANE WHERE NUME='" + nume + "' AND LOCALITATE='" + loc + "'"; ResultSet rs = stmt.executeQuery(my_query); while ( rs.next() ) { p = new Persoana(rs.getString("Nume"), rs.getString("Prenume"), rs.getString("Localitate"), rs.getInt("Salariu") ); System.out.println(""+p); } } public void adauga(Persoana p) throws Exception { String my_stmt = "INSERT INTO PERSOANE (NUME,PRENUME,LOCALITATE,SALARIU)" + " VALUES('" + p.rNume() + "','" + p.rPrenume() + "','" + p.rLocalitate()+"','" + p.rSalariu() + "');"; int i = stmt.executeUpdate(my_stmt); System.out.println(""+p); }
Clasa Agenda de mai jos conine numai metoda principal. Aceast metod prevede crearea unei conexiuni con la baza de date, a unui "obiect instruciune" stmt i a unui obiect bd de tipul BD. n continuare sunt citite de la intrare iruri de caractere i se ntreprind urmtoarele aciuni: - dac primul ir de caractere citit este "INSERT", mai sunt citite 3 iruri de caractere i un numr ntreg; prin invocarea metodei adauga a clasei BD este inserat o nou nregistrare n baza de date; - dac primul ir de caractere citit este "SELECT", atunci mai sunt citite dou iruri de caractere nume i loc i este invocat metoda cauta a clasei BD pentru listarea tuturor personelor cu numele nume i localitatea loc; - dac primul ir de caractere citit este "STOP", atunci programul se termin.
import java.sql.*; import java.util.*; class Agenda { public static void main(String[] args) throws Exception { String id,nume,prenume,loc; int sal; Persoana P; Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); String url = "jdbc:odbc:AgendaODBC"; Connection con = DriverManager.getConnection(url,"Vasile","Sile"); Statement stmt = con.createStatement(); BD bd = new BD(stmt); Scanner sc = new Scanner(System.in); for ( ; ; ) { System.out.println("*** Comanda noua : ***"); id = sc.next(); if (id.equals("STOP")) break; else if (id.equals("SELECT")) { nume = sc.next(); loc = sc.next(); bd.cauta(nume,loc);
6
} else if (id.equals("INSERT")) { nume = sc.next(); prenume = sc.next(); loc = sc.next(); sal = sc.nextInt(); P = new Persoana(nume,prenume,loc,sal); bd.adauga(P); } else System.out.println("Comanda incorecta"); } con.close(); stmt.close(); } }
va fi afiat:
Ionescu Ionescu Ionescu
class Server_BD { public static void main(String[] sss) throws Exception { ServerSocket ss = new ServerSocket(7777); Socket cs; System.out.println("Serverul a pornit"); Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); String url = "jdbc:odbc:AgendaODBC"; Connection con = DriverManager.getConnection(url,"Vasile","Sile"); Statement stmt = con.createStatement(); System.out.println("S-a creat legatura la baza de date"); while (true) { cs = ss.accept(); System.out.println("Client nou"); new Conexiune(cs,stmt); } } }
class Conexiune extends Thread { Socket cs; Statement stmt; Persoana p; String id,nume,prenume,loc; int sal;
7
Vector v; DataInputStream dis; ObjectOutputStream oos; Conexiune(Socket client, Statement s) { cs = client; stmt = s; start(); } public void run() { try { dis = new DataInputStream( cs.getInputStream()); oos = new ObjectOutputStream( cs.getOutputStream()); String sql; for( ; ; ) { id = dis.readUTF(); if(id.equals("SELECT")) { v = new Vector(); nume = dis.readUTF(); loc = dis.readUTF(); sql = "SELECT * FROM PERSOANE WHERE NUME='" + nume + "' AND LOCALITATE='" + loc + "'"; System.out.println("Comanda: " + sql); ResultSet rs = stmt.executeQuery(sql); while ( rs.next() ) { p = new Persoana(rs.getString("Nume"), rs.getString("Prenume"), rs.getString("Localitate"), rs.getInt("Salariu") ); System.out.println(""+p); v.addElement(p); } oos.writeObject(v); } else { // comanda INSERT nume = dis.readUTF(); prenume = dis.readUTF(); loc = dis.readUTF(); sal = dis.readInt(); p = new Persoana(nume, prenume, loc, sal); System.out.println(p+""); sql = "INSERT INTO PERSOANE "+ "(NUME,PRENUME,LOCALITATE,SALARIU)" + " VALUES('" + p.rNume() + "','" + p.rPrenume() + "','" + p.rLocalitate() + "','" + p.rSalariu() + "');"; System.out.println("Comanda: " + sql); stmt.executeUpdate(sql); System.out.println("S-a adaugat: "+p); } } } catch(IOException e) { } catch(SQLException e) { } } }
8
import java.io.*; import java.net.*; import java.util.*; class Client_BD { public static void main(String[] args) throws Exception { String id; Persoana P; Vector v; Socket cs = new Socket("localhost",7777); DataOutputStream dos = new DataOutputStream(cs.getOutputStream()); ObjectInputStream ois = new ObjectInputStream(cs.getInputStream()); Scanner sc = new Scanner(System.in); for ( ; ; ) { System.out.println("*** Comanda noua : ***"); id = sc.next(); if (id.equals("STOP")) break; else if (id.equals("SELECT")) { dos.writeUTF("SELECT"); dos.writeUTF(sc.next()); dos.writeUTF(sc.next()); v = (Vector) ois.readObject(); while ( !v.isEmpty() ) { P = (Persoana) v.elementAt(0); System.out.println(""+P); v.removeElementAt(0); } } else if (id.equals("INSERT")) { dos.writeUTF("INSERT"); dos.writeUTF(sc.next()); dos.writeUTF(sc.next()); dos.writeUTF(sc.next()); dos.writeInt(sc.nextInt()); } else System.out.println("Comanda incorecta"); } } }
9 unde metoda cauta ntoarce ntr-un vector nregistrrile de tip Persoana selectate. Clientul folosete clasa Client_BD_RMI:
import java.sql.*; import java.rmi.*; import java.util.*; class Client_BD_RMI { public static void main(String[] args) throws Exception { String id,nume,prenume,loc; int sal; Persoana P; Vector v; I_BD bd = (I_BD) Naming.lookup("rmi:///bd"); Scanner sc = new Scanner(System.in); for ( ; ; ) { System.out.println("*** Comanda noua : ***"); id = sc.next(); if (id.equals("STOP")) break; else if (id.equals("SELECT")) { nume = sc.next(); loc = sc.next(); v = bd.cauta(nume,loc); while ( !v.isEmpty() ) { P = (Persoana) v.elementAt(0); System.out.println(""+P); v.removeElementAt(0); } } else if (id.equals("INSERT")) { nume = sc.next(); prenume = sc.next(); loc = sc.next(); sal = sc.nextInt(); P = new Persoana(nume,prenume,loc,sal); bd.adauga(P); } else System.out.println("Comanda incorecta"); }
} }
10
ResultSet rs = stmt.executeQuery(sql); while ( rs.next() ) { p = new Persoana(rs.getString("Nume"), rs.getString("Prenume"), rs.getString("Localitate"), rs.getInt("Salariu") ); System.out.println(""+p); v.addElement(p); } return v;
public void adauga(Persoana p) throws Exception { String sql = "INSERT INTO PERSOANE (NUME,PRENUME,LOCALITATE,SALARIU)" + " VALUES('" + p.rNume() + "','" + p.rPrenume() + "','" + p.rLocalitate()+"','" + p.rSalariu() + "');"; System.out.println("Comanda: " + sql); stmt.executeUpdate(sql); System.out.println("S-a adaugat: "+p); } public static void main(String[] args) throws Exception { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); String url = "jdbc:odbc:AgendaODBC"; Connection con = DriverManager.getConnection(url,"Vasile","Sile"); Statement stmt = con.createStatement(); Server_BD_RMI bd = new Server_BD_RMI(stmt); Naming.rebind("rmi:///bd",bd); } }
urmnd ca nainte de fiecare cerere s nlocuim cmpul marcat prin '?' cu o valoare efectiv printr-o metod de setare (vezi mai jos). Gestiunea instruciunilor parametrizate este facilitat de interfaa:
public interface PreparedStatement extends Statement
11 din pachetul java.sql. Interfaa definete un obiect ce reprezint o instruciune SQL precompilat. Obiectul poate fi folosit eficient pentru a executa n mod repetat instruciunea, dar pentru seturi diferite de parametri. Descriem n continuare principalele metode ale acestei interfee.
public ResultSet executeQuery() throws SQLException este analoaga metodei cu acelai nume din interfaa Statement. public int executeUpdate() throws SQLException este analoaga metodei cu acelai nume din interfaa Statement.
Metodele de setare:
public void setTip(int i, tip t) throws SQLException seteaz parametrul cu numrul de ordine i, cu precizarea c numerotarea ncepe cu 1. Driver-ul l convertete la o valoare de tipul tipSQL i l trimite bazei de
Exemplu. Relum exemplul anterior i urmrim listarea succesiv a tuturor nregistrrilor n care salariul este mai mare dect 450, 500, 550, 600.
import java.sql.*; class Agenda1 { public static void main(String[] args) throws Exception { String id,nume,prenume,loc; int sal; Persoana P; Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); String url = "jdbc:odbc:AgendaODBC"; Connection con = DriverManager.getConnection(url,"Vasile","Sile"); Persoana p; String cerere="SELECT * FROM PERSOANE WHERE SALARIU>?"; PreparedStatement pstmt = con.prepareStatement(cerere); for (int i=400; i<650; i=i+50) { pstmt.setInt(1,i); System.out.println("Persoane cu salariul > "+i); ResultSet rs = pstmt.executeQuery(); while( rs.next() ) {
12
p = new Persoana( rs.getString("Nume"), rs.getString("Prenume"), rs.getString("Localitate"), rs.getInt("Salariu") ); System.out.println(""+p); } con.close(); pstmt.close(); }
} }
Persoane cu salariul > Ionescu Ion Ionescu Vasile Vasile Vasile Ionescu Dan Persoane cu salariul > Ionescu Ion Ionescu Vasile Vasile Vasile Persoane cu salariul > Ionescu Vasile Vasile Vasile Persoane cu salariul > Vasile Vasile
550 600