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
|