java.sql.Driver
- Obsługuje łączenie z bazą danych. Wystarczy o nim
wiedzieć, że musi być załadowany, np. tak: Class.forName("foo.bah.Driver")
.
java.sql.DriverManager
- pozwala połączyć się z bazą danych przy
użyciu jednego z załadowanych driverów (próbuje wszystkich). Służy do tego metoda
getConnection()
.
java.sql.Connection
- odpowiada pojęciu sesji z bazą danych.
java.sql.SQLException
(metoda
getNextException()
daje dostęp do wszystkich błędów). Błędy
niekrytyczne dziedziczą po java.sql.SQLWarning
(podklasa
java.sql.SQLException
), ale nie są wyrzucane tylko dodawane
do listy obiektu (np. ResultSet). Można się do nich dostać przez
getWarnings()
. Na przykład java.sql.DataTruncation
przy odczycie występuje jako warning, a przy pisaniu jako exception.
java.sql.Statement
i jednej z metod:
executeQuery(String)
- zwraca ResultSet
.
Przeznaczona dla select.executeUpdate(String)
- zwraca liczbę zmian. Przeznaczona
dla update, insert i delete.execute(String)
- wersja uniwersalna, ale zwraca true/false
w zależności, czy był jakiś wynik zapytania. Można się wspomagać metodami
getResultSet()
i getUpdateCount
.ResultSet
. Należy o nim myśleć
jak o kursorze. Dla każdego Statement
powinien być otwarty co najwyżej
jeden kursor. Podstawowe metody to:
XXX getXXX(int|String)
- parametrem jest numer lub nazwa kolumny
(XXX oznacza typ jdbc). Możliwe są konwersje typów. Po użyciu zalecane jest
sprawdzenie, czy nie było null
przy pomocy metody wasNull()
.
Dla obiektów (np. String) null
jest reprezentowany naturalnie, dla typów
podstawowych będzie to jakaś wybrana wartość.boolean next()
- przesuwa na następny wiersz.
Jeżeli skorzystamy z przeciążonej wersji createStatement()
możemy sprawić, iż
po otrzymywanych ResultSet
można się poruszać również wstecz. Wersja
bezparametrowa odpowiada wywołaniu createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY)
. Pozostałe dozwolone wartości dla pierwszego parametru:
ResultSet.TYPE_SCROLL_SENSITIVE
i ResultSet.TYPE_SCROLL_INSENSITIVE
umożliwiają poruszanie się wstecz (różnica między nimi i trzeci parametr są opisane dalej).
Przeciążone wersje posiadają również metody prepareStatement()
i prepareCall()
.
Kilka przydatnych metod ResultSet
to: previous()
, absolute()
,
relative()
, getRow()
, afterLast()
, beforeFirst()
,
first()
, last()
, isFirst()
, isLast()
,
isBeforeFirst()
, isAfterLast()
.
Connection
).
Zmieniamy przy pomocy setAutoCommit()
. Ręczna obsługa poprzez: commit()
i rollback()
.
Można używać punkty nawrotu setSavePoint()
i
releaseSavePoint()
i posługiwać się przeciążoną wersje
commit()
i rollback()
.
Connection
, Statement
i ResultSet
mają close()
.
Od implementacji JDBC zależy, czy trzeba ją stosować. Zamknięcie Connection
powinno
zamknąć Statement
i analogicznie zamknięcie Statement
powinno zamknąć
ResultSet
.
setFetchDirection()
- możliwe parametry to: ResultSet.FETCH_FORWARD
,
ResultSet.FETCH_RERVERSE
, ResultSet.FETCH_UNKNOWN
.setFetchSize()
- podajemy liczbę przesyłanych wierszy. 0 - pozwala zgadywać driverowi.
Oczywiście nie ogranicza to w żaden sposób liczby dostępnych wierszy, czy możliwości przeglądania
wyników.Statement
można wykorzystać
PreparedStatement
. Dostajemy je z obiektu połączenia dzięki metodzie
prepareStatement()
(wcześniej było create), której przekazujemy kod sql,
ale zamiast danych wstawiamy ?
. Przy pomocy setXXX()
dowiązujemy
wartości. Jeżeli potrzebujemy zwolnić zasoby to clearParameters()
.
CallableStatement
. Jej egzemplarz jest zwracany przez metodę prepareCall()
obiektu Connection
. Składnia sql jest specyficzna dla JDBC, np.
{call proc_name[(?,?)]}
albo {? = call fun_name[{?,?}]}
.
Dane wyjściowe trzeba zarejestrować żeby był znany ich typ. Służy do tego metoda
registerOutParameter(int, int)
, gdzie drugi parametr określa typ danych.
Klasa java.sql.Types
zawiera definicje odpowiednich stałych.
Paremetry wejściowe dowiązujemy tak jak poprzednio przy pomocy setXXX()
.
Statement
i jego potomkowie mają metodę addBatch()
, która
umożliwia dodania kolejnych poleceń sql do jednego obiektu Statement
.
Dla Statement
przyjmuje ona jako parametr napis z poleceniem, a przy
PreparedStatement
i CallableStatement
jej odmiana
bezparametrowa akceptuje dotychczas dowiązane parametry jako nowe polecenie i
umożliwia rozpoczęcie dowiązywania parametrów dla kolenego.
Całą paczkę wykonuje się poprzez executeBatch()
. W wyniku dostajemy
tablicę liczb wierszy zmodyfikowanych przez poszczególne komendy. Jeżeli wystąpił wyjątek
BatchUpdateException
to tablicę z częściowym wynikiem możemy dostać dzięki
metodzie getUpdateCounts()
i z jej rozmiaru odczytać ile poleceń się powiodło.
Connection
ma metody getTransactionIsolation()
i
setTransactionIsolation()
, które pozwalają kontrolować poziom izolacji
sesji.ResultSet
można dokonywać zmian danych w bazie. Aby, była taka
możliwość należy w metodzie createStatement()
jako drugi parametr przekazać
ReasultSet.CONCUR_UPDATABLE
.
Zmian wartości w aktualnym wierszu dokonujemy przez metody updateXXX()
,
a zatwierdzamy wywołaniem updateRow()
. Możemy też usunąć cały wiersz
deleteRow()
lub wstawić nowy insertRow()
. Wstawiany wiersz
należy najpierw przygotować moveToInsertRow()
, a potem
updateXXX()
i getXXX()
.
Istnieje jednak kilka ograniczeń:
ResulSet
musi zawierać dane z pojedyńczej tabeli.ResultSet
zostanie mu przypisany SQLWarning
.
Dopiero próba wykorzystania niedostępnej funkcjonalności grozi zgłoszeniem wyjątku.
ResultSet
zależy od poziomu izolacji oraz
parametrów podanych metodom createStatement()
, prepareStatement()
,
czy prepareCall()
.
ResultSet.TYPE_SCROLL_INSENSITIVE
- nie widać żadnych zmian przeprowadzonych
w przez inne transakcje, ani nawet składniki tej samej transakcji.ResultSet.TYPE_SCROLL_SENSITIVE
- widoczne są efekty instrukcji UPDATE
wykonanych w ramach tej samej transakcji, a nawet w ramach innych, jeżeli zezwala na to
poziom izolacji transakcji. W tym drugim przypadku dopiero po wywołaniu refreshRow()
.
Instrukcje UPDATE, które zmieniają kolejność wierszy w ResultSet
traktowane
są jako DELETE i INSERT przez co nie ma gwarancji co do ich widoczności.java.sql.Array
.
Obiekty implementujące ten interfejs dostajemy przez metodzię getArray()
z klasy ResultSet
. Z metod zapewnionych przez interfejs warte wspomnienia są:
getArray()
- zwraca tablicę javy,getResultSet()
- umożliwia obsługę tablicy java.sql.Array
jako ResultSet
.
Niestety nie ma sposobu na skonstruowanie obiektu implementującego Array
w
sposób niezależnego od drivera, aby wykorzystać go w setArray()
.
JDBC zapewnia również obsługę typów Bloby i Cloby.
java.util.Map
wprowadzić swoje własne. Kluczami mapy są napisy zawierające
nazwy typów jdbc, a wartościami odpowiadające im obiekty java.lang.Class
.
Własne mapowanie może mieć zasięg całej sesji - metoda setTypeMap()
obiektu
Connection
lub pojedyńczego wywołania metody getXXX()
, np.
getObject(1, mojeMapowanie)
.
Każda klasa pojawiająca się w takiej mapie typów musi implementować interfejs java.sql.SQLData
.
java.sql.ResultSetMetaData
- uzyskujemy z obiektu ResultSet
przez metodę getMetaData()
,java.sql.DatabaseMetaData
- uzyskujemy z obiektu Connection
również przez metodę getMetaData()
.DriverPropertyClass
.
USERNAME
i
PASSWORD
w klasie Common.java
!
java moje_jdbc.Data
.
java moje_jdbc.Select
.java moje_jdbc.Commit 1313 "ala" 71.17
i drugi raz java moje_jdbc.Commit 1312 "ala ma kota" 11.99
.Select
, aby wykorzystywał przeciążoną postać
createStatement()
, a ResultSet
był przeglądany od końca.
Data
.Data
.