InMoST
Wielkopolska sieć współpracy w zakresie innowacyjnych metod wytwarzania oprogramowania
Termin realizacji: 01.08.2005 – 31.07.2007
Dostęp do baz danych
przez interfejs JDBC
Bartosz Walter
Szkolenie finansowane ze środków Europejskiego Funduszu Społecznego (75%) i budżetu
państwa (25%) w ramach Zintegrowanego Programu Operacyjnego Rozwoju Regionalnego
Wprowadzenie
JDBC (Java DataBase Connectivity) jest biblioteką
Javy (zbiorem interfejsów i klas) służącą do
wykonywania operacji na bazach danych
JDBC z punktu widzenia aplikacji nie zależy od
wykorzystywanego systemu bazy danych, dzięki
czemu stosunkowo łatwo zmienić go na inny
Biblioteka znajduje się w Java SDK w pakietach
java.sql.* i javax.sql.*
Odczyt informacji z bazy danych
1. Załadowanie sterownika JDBC specyficznego dla
konkretnej bazy danych (MySQL, PostgreSQL, Oracle
etc.) i zarejestrowanie go w JVM
2. Utworzenie obiektu Connection, reprezentującego
połączenie z bazą danych
3. Utworzenie obiektu Statement, reprezentującego
instrukcję do wykonania w bazie danych
4. Wykonanie instrukcji; w przypadku zapytań –
pobranie obiektu ResultSet udostępniającego wyniki
5. Przetworzenie obiektu ResultSet
6. Zamknięcie obiektów ResultSet, Statement i
Connection
Sterownik JDBC
baza
danych
komunikacja z
serwerem bazy danych
sterownik
Sterownik JDBC jest niewielką biblioteką
umożliwiającą operacje na bazie danych specyficznej
dla sterownika
Każdy system zarządzania bazą danych wymaga
własnego sterownika JDBC. Są one dostarczane przez
producentów systemów zarządzania bazami danych
protokół
JDBC
Aplikacja
użytkownik
Ładowanie sterownika JDBC
Sterownik JDBC musi być widoczny dla aplikacji, tzn.
musi znajdować się na jej ścieżce klas (CLASSPATH)
W Eclipse wystarczy dołączyć bibliotekę do projektu
Załadowanie klasy sterownika
Class.forName("org.hsqldb.jdbcDriver");
// w przypadku braku klasy – wyjątek SQLException
DriverManager.registerDriver(
new org.hsqldb.jdbcDriver());
// w przypadku braku klasy – wyjątek ClassNotFoundEx.
Utworzenie obiektu Connection
Obiekt Connection reprezentuje fizyczne połączenie
do bazy danych
Connection conn = DriverManager.getConnection(
"jdbc:hsqldb:hsql:@localhost",
"student", "wsb");
URL bazy danych
nazwa użytkownika i hasło
jdbc:hsqldb:hsql:@komputer.domena.pl:9001/bazadanych
protokół
adres serwera
port nazwa bazy danych
Utworzenie obiektu Statement
Obiekt Statement reprezentuje instrukcję języka SQL,
którą możemy wykonać w danym połączeniu
Tworzeniem obiektu Statement zajmuje się obiekt
Connection
Obiekt Statement zajmuje się m.in.. weryfikacją
poprawności polecenia
Statement stm = conn.createStatement();
Utworzenie obiektu Statement – cd.
W przypadku wielokrotnego wykonywania tej samej
operacji SQL z różnymi danymi można skorzystać z
obiektu PreparedStatement
PreparedStatement w odróżnieniu od obiektu
Statement nie wykonuje za każdym razem weryfikacji
poprawności polecenia SQL, co poprawia wydajność
PreparedStatement pstm =
conn.prepareStatement("SELECT * FROM STUDENCI");
Utworzenie obiektu Statement – cd.
Obiekt PreparedStatement może uwzględniać
niekonkretne wartości atrybutów polecenia SQL,
które będą ukonkretniane w momencie wykonywania
polecenia
Pozwala to na efektywniejsze wykonywanie poleceń
PreparedStatement pstm =
conn.prepareStatement(
"select * from STUDENCI where ID=? and IMIE=?");
pstm.setInt(1, 100);
pstm.setString(2, 'Jan');
ResultSet rs = pstm.executeQuery();
Wykonanie polecenia SQL
Obiekt Statement wykonuje przekazane mu polecenie
W przypadku zapytań wynikiem wykonania polecenia
jest obiekt ResultSet, który zawiera odczytane
informacje z bazy danych
W przypadku poleceń INSERT lub UPDATE wynikiem
jest wartość int oznaczająca liczbę zmodyfikowanych
rekordów
ResultSet rs = stm.executeQuery(
"SELECT * FROM STUDENCI");
int liczbaRekordów = stm.executeUpdate(
"INSERT INTO STUDENCI values (1, "Nowak", "Jan");
Przetwarzanie obiektu ResultSet
Obiekt ResultSet jest obiektem, który zawiera
pierwszy rekord danych
Odczyt kolejnych rekordów odbywa się przez
wywołanie metody next(), która określa też, czy
kolejny rekord istnieje
ResultSet rs = stm.executeQuery(
"SELECT * FROM STUDENCI");
while (rs.next()) {
// pętla trwa dopóki istnieje kolejny rekord
// przetworzenie rekordu
}
Przetwarzanie obiektu ResultSet – cd.
Obiekt ResultSet posiada metody pozwalające
odczytywać pola bieżącego rekordu jako różne typy
(int getInt(), String getString(), Date getDate() etc.)
Pola można adresować nazwą pola
ResultSet rs = stm.executeQuery(
"SELECT ID, IMIE, NAZWISKO FROM STUDENCI");
while (rs.next()) {
String id = rs.getInt("ID");
String imie = rs.getString("IMIE");
String nazwisko = rs.getString("NAZWISKO");
}
Przetwarzanie obiektu ResultSet – cd.
...lub indeksem pola w zapytaniu
ResultSet rs = stm.executeQuery(
"SELECT ID, IMIE, NAZWISKO FROM STUDENCI");
while (rs.next()) {
String id = rs.getInt(1);
String imie = rs.getString(2);
String nazwisko = rs.getString(3);
}
Zamknięcie otwartych obiektów
Wszystkie otwarte obiekty rezerwują zasoby, dlatego
warto zamykać je po wykorzystaniu
Wszystkie obiekty Connection, Statement i ResultSet
posiadają metodę close()
rs.close();
stm.close();
conn.close();
Cały przykład
public class StudenciDB {
public static void main(String[] args) throws SQLException {
Class.forName("org.hsqldb.jdbcDriver");
Connection conn = DriverManager("jdbc:hsqldb:hsql://localhost/",
"sa", "");
Statement stm = conn.createStatement();
ResultSet rs = stm.executeQuery(
"SELECT ID, IMIE, NAZWISKO FROM STUDENCI");
while (rs.next()) {
System.out.println("Imie: " + rs.getString(2) + ", nazwisko: " + rs.getString(3));
}
rs.close();
stm.close();
conn.close();
}
}
Transakcje
Transakcje modyfikujące bazę danych muszą zostać
zatwierdzone lub anulowane
Służą do tego metody commit() i rollback() w klasie
Connection
conn.commit(); // zatwierdzenie
conn.rollback(); // anulowanie
Aby nie zapomnieć o zatwierdzeniu transakcji można
ustawić automatyczne zatwierdzanie
conn.setAutoCommit(true);
Obsługa transakcji złożonych
Transakcje składające się z wielu poleceń SQL mogą
być wykonywane w jednym bloku
try {
conn.setAutoCommit(false);
pstm.executeUpdate(sql1);
pstm.executeUpdate(sql2);
conn.commit();
// zatwierdzenie operacji
} catch (SQLException ex) {
System.out.println("Nie udało się...");
conn.rollback(); // anulowanie operacji
} finally {
conn.close();
}
Wydajność JDBC
Wydajność JDBC może w wielu przypadkach być
niewystarczająca.
Aby poprawić wydajność realizacji transakcji przez
JDBC, można:
zastosować mechanizm puli połączeń do bazy danych, dzięki
czemu połączenia nie są tworzone i zamykane, a pobierane i
zwracane do puli
stosować obiekt PreparedStatement zamiast Statement
wykonywać wiele operacji SQL w jednej transakcji z
wywołaniem commit() na końcu
Obsługa wyjątków
Niemal każda operacja JDBC może spowodować
zgłoszenie wyjątku SQLException
Nieobsłużenie wyjątku może spowodować porzucenie
otwartego połączenia do bazy danych
try {
// wykonujemy różne operacje JDBC
} catch (SQLException ex) {
System.out.println(ex);
} finally {
if (conn != null) // próba zamknięcia połączenia
try { conn.close();
} catch (SQLException ex2) {}
}
Q&A