ALTE DOCUMENTE
|
|||||
JDBC (Java DataBase Connectivity) este o parte a Java API dedicata conectarii la baze de date. Utilizând JDBC, putem executa instructiuni SQL pentru orice baza de date relationala.
Etapele principale într-o aplicatie ce foloseste JDBC sunt urmatoarele:
deschiderea unei conexiuni catre baza de date;
crearea unui "obiect instructiune" prin care transmitem instructiuni SQL catre gestionarul bazei de date;
regasirea rezultatelor.
Principalele clase si interfete se gasesc în pachetul java.sql. Dintre acestea vom prezenta doar urmatoarele interfete:
public interface Connection
stabileste conexiunea la baza de date;
public interface Statement
creaza un obiect instructiune ce contine o instructiune SQL si îl transmite bazei de date;
public interface ResultSet
permite regasirea rezultatelor interogarii;
public interface PreparedStatement
permite lucrul cu instructiuni SQL cu parametri.
Vom prezenta în continuare numai principalele aspecte legate de JDBC.
Pentru a putea ajunge la o aplicatie efectiva, presupunem ca cititorul este familiarizat cu forma instructiunilor SQL si ca baza de date este creata folosind Microsoft Access. De asemenea, presupunem pentru moment ca baza de date este locala.
Fie Agenda numele bazei de date, în care folosim tabelul Persoane. Secventa standard de actiuni ce trebuie întreprinsa este urmatoarea:
deschid Microsoft Access
Blank Access Database
merg în directorul meu
File Name Agenda
Create
selectez: Create Table in Design view si Tables
Open
introduc numele câmpurilor + tipul lor
închid
Salvez sub numele: Persoane
fara cheie primara
Click pe Persoane: pot introduce înregistrari
închid toate ferestrele.
Pentru exemplificare, plecam de la urmatorul continut al tabelei Persoane
Baza de date astfel creata este însa particulara si nu este recunoscuta ca atare de orice sistem. De aceea trebuie folosit un "intermediar" care sa permita accesarea si exploatarea ei. Un astfel de intermediar este ODBC (Open DataBase Connectivity). Baza de date trebuie conectata la o sursa de baze de date ODBC, prin înregistrarea ei la driver-ul ODBC.
Adresa sursei de date se precizeaza prin:
String url="jdbc:odbc:sursa_date"
Presupunem ca numele sursei de date este AgendaODBC. Mergem succesiv în:
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.
Încarcarea driver-ului ODBC se realizeaza prin:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Conectarea la baza de date se realizeaza prin crearea unui obiect de tipul Connection (interfata care încearca sa realizeze o conexiune la baza de date asociata sursei de date ODBC). Modalitatea tipica de conectare este urmatoarea:
try
catch (SQLException e)
Se observa ca trebuie trimis numele utilizatorului si o parola, pentru o eventuala validare a accesului la baza de date.
Pentru executarea de instructiuni SQL trebui mai întâi creat un "obiect instructiune", adica un obiect de tipul interfetei Statement
Statement stmt = con.createStatement();
unde createStatement este o metoda a interfetei Connection. pe baza acestui obiect este posibila executarea de instructiuni SQL, cu primirea rezultatelor cautarii.
În continuare trebuie creat un sir de caractere care sa reprezinte o comanda SQL valida:
String sql = "...";
Urmeaza transmiterea cererii si obtinerea rezultatului interogarii folosind una dintre metodele:
public ResultSet executeQuery(String sql) throws SQLExceptionunde sql
reprezinta o
instructiune SQL de tip SELECT
. Este întors un obiect de tipul ResultSet care permite regasirea
rezultatelor cererii;
unde sql reprezinta o
instructiune SQL de unul dintre tipurile INSERT
UPDATE
, sau DELETE
. Este întors numarul
liniei (înregistrarii) afectate.
Interfata:
public interface ResultSet
permite regasirea, sub forma unui tabel, a rezultatelor cautarii la executarea unei metode executeQuery. Un obiect de acest tip mentine un cursor la linia curenta din tabel, initial la prima linie a acestuia. Dintre metodele interfetei ResultSet descriem deocamdata numai urmatoarele:
public boolean next()
întoarce true daca si numai daca mai exista linii în rs, caz în care se trece la urmatoarea înregistrare;
public gettip(String s)
întoarce continutul câmpului cu numele s din înregistrarea curenta ca o valoare de tipul tip din Java; tip poate fi String Int etc.
Observatie. Obiectele con si stmt trebuie "închise" în final prin invocarea metodei close()
Înregistrarile (liniile) din baza de date cu care lucram corespund informatiilor despre o persoana si au câmpurile Nume, Prenume, Localitate si Salariu, cu semnificatii evidente. Corespunzator, scriem clasa Persoana în care constructorul initializeaza câmpurile, iar metodele întorc valorile lor.
class Persoana
public String rNume()
public String rPrenume()
public String rLocalitate()
public int rSalariu()
public String toString()
Asupra bazei de date vom executa doar doua operatii:
selectarea tuturor înregistrarilor cu un nume si o localitate date:
SELECT * FROM PERSOANE WHERE NUME='...' AND LOCALITATE='...'
pentru care vom folosi metoda executeQuery
inserarea unei noi înregistrari:
INSERT INTO PERSOANE (NUME,PRENUME,LOCALITATE,SALARIU)
VALUES('...','...','...','...')
pentru care vom folosi metoda executeUpdate
Aceste operatii corespund metodelor cauta si adauga din clasa BD, clasa care are un câmp stmt de tipul Statement, care primeste valoare prin constructor:
import java.sql.*;
class BD
public void cauta (String nume, String loc)
throws Exception
}
public void adauga(Persoana p) throws Exception
Clasa Agenda de mai jos contine numai metoda principala. Aceasta metoda prevede crearea unei conexiuni con la baza de date, a unui "obiect instructiune" stmt si a unui obiect bd de tipul BD. În continuare sunt citite de la intrare siruri de caractere si se întreprind urmatoarele actiuni:
daca primul sir de caractere citit este "INSERT", mai sunt citite 3 siruri de caractere si un numar întreg; prin invocarea metodei adauga a clasei BD este inserata o noua înregistrare în baza de date;
daca primul sir de caractere citit este "SELECT", atunci mai sunt citite doua siruri de caractere nume si loc si este invocata metoda cauta a clasei BD pentru listarea tuturor personelor cu numele nume si localitatea loc
daca primul sir de caractere citit este "STOP", atunci programul se termina.
import java.sql.*;
class Agenda
else if (id.equals("INSERT"))
else IO.writeln("Comanda incorecta");
}
con.close(); stmt.close();
}
De exemplu, daca vom introduce:
"SELECT"
"Ionescu" "
va fi afisat:
Ionescu Ion
Ionescu Vasile
Ionescu Dan
Deoarece se vor trimite la distanta obiecte de tipul Persoana, aceasta trebuie sa implementeze interfata Serializable
import java.io.*;
class Persoana implements Serializable
public String rNume()
public String rPrenume()
public String rLocalitate()
public int rSalariu()
public String toString()
Serverul va folosi clasa Server_BD.java
import java.io.*; import java.sql.*;
import java.util.*; import java.net.*;
class Server_BD
}
class Conexiune extends Thread
public void run()
oos.writeObject(v);
}
else
}
}
catch(IOException e)
catch(SQLException e)
}
Clientii vor folosi clasa Client_BD.java
import java.io.*; import java.net.*; import java.util.*;
class Client_BD
}
else if (id.equals("INSERT"))
else IO.writeln("Comanda incorecta");
}
}
Java ofera multe posibilitati de a rezolva aceasta problema. Dintre acestea alegem mecanismul invocarii la distanta (RMI). Practic, vom scrie un server de Web ce va functiona pe masina pe care se afla baza de date.
Vom descrie pas cu pas modificarile ce trebuie aduse programului de mai sus.
Deoarece se transmit la distanta obiecte de tipul clasei Persoana, aceasta trebuie sa fie serializabila; ea se afla atât pe client, cât si pe server.
import java.io.*;
class Persoana implements Serializable
public String rNume()
public String rPrenume()
public String rLocalitate()
public int rSalariu()
public String toString()
Tot atât pe client cât si pe server se va afla interfata I_BD
import java.rmi.*; import java.sql.*; import java.util.*;
interface I_BD extends Remote
unde metoda cauta întoarce într-un vector înregistrarile de tip Persoana selectate.
Clientul foloseste clasa Client_BD_RMI
import java.sql.*; import java.rmi.*; import java.util.*;
class Client_BD_RMI
}
else if (id.equals("INSERT"))
else IO.writeln("Comanda incorecta");
}
}
Serverul foloseste clasa Server_BD_RMI
import java.sql.*; import java.util.*;
import java.rmi.*; import java.rmi.server.*;
class Server_BD_RMI extends UnicastRemoteObject
implements I_BD
public Vector cauta(String nume, String loc)
throws Exception
return v;
}
public void adauga(Persoana p) throws Exception
public static void main(String[] args) throws Exception
Uneori programul trimite cereri de aceleasi tip, dar cu alte valori pentru unul sau mai multe câmpuri. De exemplu putem trimite cereri multiple în care doar valoarea unui câmp (unor câmpuri) difera. În aceste situatii este utila, dar si eficienta, folosirea unor instructiuni SQL în care apar parametri. Concret, în locul câmpului (câmpurilor) vom introduce caracterul , umând ca acesta sa fie înlocuit cu o valoare efectiva înainte de cererea propriu-zisa. Eficienta deriva din faptul ca instructiunile parametrizate sunt precompilate.
Pentru exemplul considerat mai sus putem forma cererea parametrizata:
SELECT * FROM PERSOANE WHERE SALARIU>?
urmând ca înainte de fiecare cerere sa înlocuim câmpul marcat prin cu o valoare efectiva printr-o metoda de setare (vezi mai jos).
Gestiunea instructiunilor parametrizate este facilitata de interfata:
public interface PreparedStatement extends Statement
din pachetul java.sql. Interfata defineste un obiect ce reprezinta o instructiune SQL precompilata. Obiectul poate fi folosit eficient pentru a executa în mod repetat instructiunea, dar pentru seturi diferite de parametri.
Descriem în continuare principalele metode ale acestei interfeteeste analoaga metodei cu acelasi nume din interfata Statement
public int executeUpdate() throws SQLExceptioneste analoaga metodei cu acelasi nume din interfata Statement
Metodele de setare:
public void setTip(int i, tip t) throws SQLException
seteaza parametrul cu numarul de ordine i, cu precizarea ca numerotarea începe cu 1. Driver-ul îl converteste la o valoare de tipul tipSQL si îl trimite bazei de date. Iata câteva cazuri particulare:
Tip |
tip |
tipSQL |
Boolean |
boolean |
BIT |
Byte |
byte |
TINYINT |
Short |
short |
SMALLINT |
Int |
int |
INTEGER |
Long |
long |
BIGINT |
Float |
float |
FLOAT |
Double |
double |
DOUBLE |
BigDecimal |
BigDecimal |
NUMERIC |
String |
String |
VARCHAR |
Date |
Date |
DATE |
Time |
Time |
TIME |
Ref |
Ref |
REF |
URL |
URL |
DATALINK |
Exemplu. Reluam exemplul anterior si urmarim listarea succesiva a tuturor înregistrarilor în care salariul este mai mare decât 450, 500, 550, 600.
import java.sql.*;
class Agenda1
}
con.close(); pstmt.close();
}
Executarea programului conduce la afisarea urmatoarelor rezultate:
Persoane cu salariul > 450
Ionescu Ion
Ionescu Vasile
Vasile Vasile Cluj 610
Ionescu Dan
Persoane cu salariul > 500
Ionescu Ion
Ionescu Vasile
Vasile Vasile Cluj 610
Persoane cu salariul > 550
Ionescu Vasile
Vasile Vasile Cluj 610
Persoane cu salariul > 600
Vasile Vasile Cluj 610
|