Zakład Inżynierii Oprogramowania

Transkrypt

Zakład Inżynierii Oprogramowania
Zakład Inżynierii Oprogramowania
Programowanie w języku Java
WYKŁAD
dr inż. Piotr Zabawa
Certyfikowany Konsultant IBM/Rational
e-mail: [email protected]
www:
http://www.pk.edu.pl/~pzabawa
14.04.2014
Zakład Inżynierii Oprogramowania
WYKŁAD 8
Trwałość w Java – cz. 1
Wykład w zakresie JDBC został w znacznej mierze oparty
o źródła, których autorem jest Jakob Jenkov
dr inż. Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java
Celem wykładów poświęconych trwałości w Java nie jest
wprowadzenie w zagadnienia relacyjnych baz danych ani w język SQL.
Te zagadnienia zostaną opanowane przez studentów w ramach
przedmiotów poświęconych bazom danych.
Wykład został podzielony na dwie części:
• JDBC – standard wymagający znajomości SQL
• JPA – standard pozwalający uniknąć znajomości SQL
Pierwsza część może okazać się przydatna osobom pragnącym tą
drogą poznać SQL.
Druga część pozwala uniknąć znajomości SQL osobom, które
przywiązują większą wagę do tworzonego przez nich oprogramowania niż
do samej kwestii składowania danych.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java
Wprawdzie relacyjne bazy danych są relatywnie starą technologią, to
jednak nadal dominują na rynku. Było wiele prób zastąpienia ich kolejno
przez obiektowe, obiektowo-relacyjne, XML’owe, a obecnie przez
NoSQL’owe bazy danych. Ale jak dotąd, żadna z propozycji nie odniosła
sukcesu. Dlatego właśnie dominują obecnie relacyjne bazy danych.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java
W ramach języka Java trwałość można zapewnić na wiele sposobów:
• Wprost w Java SE
– JDBC (Java Database Connectivity) – odpowiednik ODBC
• Z wykorzystaniem frameworków
– JPA2 (Java Persistence API) – standard wykorzystany np. w
• Hibernate
• EclipseLink
• TopLink
– EJB3 (Enterprise Java Beans) – framework wspierający m.in.
trwałość
– Spring Data (Spring Data JPA, Spring Data JDBC Extensions)
– Seam
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java
Java posiada wsparcie do obsługi trwałości nie tylko w zakresie
relacyjnych baz danych, lecz również NoSQL’owych baz danych
zyskujących stopniowo na znaczeniu. Dobrym narzędziem jest projekt
Spring Data zawierający szereg podprojektów dedykowanych do różnych
rodzajów baz danych i wprowadzających ujednolicenie do wszystkich
podejść za pomocą podprojektu Spring Data Commons.
Jednak na zajęciach skoncentrujemy się jedynie na zagadnieniu
mapowania obiektowo-relacyjnego, czyli ORM (Object-Relational
Mapping), a więc na dostępie do relacyjnych baz danych.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java
Interesować nas będą jedynie dwa z wymienionych wyżej podejść:
• JDBC – niskopoziomowe działanie bliskie SQL, ale za to znaczna
kontrola nad implementacją warstwy trwałości
• JPA2/Hibernate – programowanie wysokopoziomowe z możliwością
niskopoziomowej optymalizacji, narzędzia forward- i reverseengineering, XML ze strukturą bazy danych
Warto mieć na uwadze, że frameworki wprowadzają swoje
wysokopoziomowe języki zapytań, zwane ogólnie EL (Expression
Languages).
Są też dodatkowe języki związane z przeprowadzaniem operacji na
relacyjnych bazach danych, np. DDL (Data Definition Language)
wykorzystywany m.in. z poziomu narzędzi modelowania w UML do
generowania struktury bazy danych z modelu.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java
Dawniej wykorzystywany był cały szereg rozwiązań wspierających
dostęp do relacyjnych baz danych, jednak z czasem rozwiązania o
mniejszym znaczeniu zostały zapomniane lub wchłonięte przez inne
rozwiązania.
Dobrym przykładem jest standard JPA, który scalił ze sobą
rozwiązania takie jak EJB 2 CMP, JDO (nie odniósł sukcesu wśród
dostawców frameworków Java EE, ale trafił do standardu), Hibernate oraz
TopLink API.
Należy również mieć na względzie, że dostępne frameworki nie są
tylko implementacją standardów. Dany framework na ogół:
• Stanowi realizację dużej części, ale nie całości standardu
• Proponuje własne rozwiązania wykraczające poza standard, a
pozwalające na konkurowanie z innymi implementacjami standardu.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java
Znaczenie wzorców korporacyjnych w dostępie do danych.
Istotną rolę odgrywają następujące architektoniczne wzorce
korporacyjne:
• DAO (Data Access Object)
• DTO (Data Transfer Object)
• Active Record
• Broker
• SDO = JDO + DTO
(Service Data Object = Java Data Object + Data Transfer Object)
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java
Wartym zainteresowania w kontekście trwałości jest wzorzec
architektoniczny DAO (Data Access Object), który zostanie również
omówiony ze względu na jego duże znaczenie praktyczne.
Wzorzec ten wprowadza dodatkową warstwę (dlatego jest
architektoniczny a nie projektowy) do systemu softwerowego. Rzutuje to
wprawdzie negatywnie na efektywność operacji na danych, ale nie zawsze
ona jest najważniejsza. Wzorzec ten uniezależnia dodatkowo warstwę
logiki biznesowej od warstwy danych, co ułatwia wprowadzanie zmian.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java
Trudno jednoznacznie przesądzić które z podejść (ORM lub JDBC)
jest lepsze. Są zwolennicy jednego lub drugiego, zwolennicy
poszczególnych standardów lub narzędzi. Są również tacy, którzy nie
wierzą w ORM a nawet w obiektowość i preferują JDBC. Są też tacy,
którzy za jedyną słuszną drogę uważają obiektowe bazy danych.
Wydaje się jednak, że właściwym podejściem jest stosowanie takiego
podejścia, które odpowiada danej osobie. Większym problemem jest
dokonanie wyboru dla przedsiębiorstwa wytwarzającego
oprogramowanie. Jednak na pewno warto przekonać się o zaletach
zarówno jednego jak i drugiego podejścia. W przeciwnym razie trudno
podjąć odpowiednią decyzję. Dalej podane zostały argumenty za
używaniem (lub nieużywaniem) JPA i ORM.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
JDBC
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
JDBC API jest interfejsem programowym zapewniającym dostęp do
relacyjnej bazy danych z poziomu języka Java w sposób niemal
niezależny od serwera bazy danych. Stanowi więc mechanizm abstrakcji,
którego realizacją są konkretne serwery bazodanowe.
Standaryzuje ono następujące operacje:
• Nawiązanie połączenia z bazą danych
• Wykonanie zapytań na bazie danych
• Nawigację po wynikach zapytania
• Modyfikowanie danych w bazie
Standaryzacji nie podlega jednak sam język zapytań SQL – jest on
różny dla różnych serwerów baz danych.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
JDBC zapewnia dostęp niskopoziomowy do bazy danych
umożliwiając programiście posługiwanie się językiem zapytań SQL.
Język ten zaliczany jest do paradygmatów deklaratywnych
oprogramowania. Jego wyrażenia określają cel a nie sposób dojścia do
niego.
Poszczególni dostawcy serwerów bazodanowych konkurują między
sobą m.in. zapewniając zróżnicowane wersje języka SQL. Zatem
wykorzystanie standardu JDBC pozwala skorzystać programiście Java w
pełni z oferty producentów tych serwerów.
Jednak niskopoziomowe operacje mogą być niewygodne w użyciu.
Dlatego w kolejnym wykładzie zostaną zaprezentowane inne rozwiązania.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
•
•
Pakiety standardowej biblioteki Java zawierające JDBC:
java.sql
javax.sql
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
•
•
•
•
Struktura JDBC API:
Sterowniki JDBC (JDBC Drivers)
Połączenia (Connections)
Stwierdzenia (Statements)
Zbiory wyników (Result Sets)
•
•
•
•
Podstawowe scenariusze użycia JDBC API:
Zapytania kierowane do bazy danych (odczyt danych)
Zapytania do bazy danych o meta-dane
Update bazy danych
Wykonywanie transakcji
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
JDBC Drivers
Zadaniem tych elementów standardu JDBC jest implementacja
interfejsów JDBC. Implementacja ta zależy od serwera bazy danych.
Jednak interfejsy są od niego niezależne. Można więc podmienić
sterownik (podmienić serwer bazy danych) nie zmieniając kodu aplikacji
– w sytuacji idealnej, ze względu na różnice w funkcjonalności i w SQL.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Connections
Po zainicjowaniu drivera umożliwiają one nawiązanie jednego lub
więcej połączeń z bazą danych poprzez serwer bazodanowy.
Całą komunikacja aplikacji w Java z bazą danych przebiega wyłącznie
poprzez Connections.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Statements
Stwierdzenia służą do wykonywania zapytań o dane i wprowadzania
zmian do danych w bazie. Istnieje kilka różnych stwierdzeń
pozwalających na wykonywanie różnych zapytań.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Result Sets
W wyniku wykonania zapytania można uzyskać jego wynik w postaci
ResultSet. Klasa ta umożliwia nawigowanie po jej obiektach w celu
uzyskania wyników zapytania z poziomu języka Java, a więc w sposób
obiektowy.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Podstawowe scenariusze
•
•
•
•
Zapytania kierowane do bazy danych – noszą one nazwę zapytań (query) i
polegają wyłącznie na odczycie danych z bazy. Są najczęściej używanymi
operacjami.
Zapytania do bazy danych o meta-dane – polegają na uzyskaniu od bazy
danych informacji o jej strukturze (tabelach, kolumnach, typach danych,
relacjach); są relacyjno-bazo-danowym odpowiednikiem klasowoobiektowego mechanizmu refleksji dostępnego w Java
Update bazy danych – operacje te polegają na zapisie do bazy danych; zapis
może dotyczyć wstawiania nowych rekordów lub modyfikowania istniejących
Wykonywanie transakcji – polega na łącznym wykonywaniu wielu operacji na
bazie danych z jednoczesną gwarancją wykonania ich wszystkich (sukces) lub
niewykonania żadnej z nich (porażka)
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
źródło: Jakob Jenkov
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
•
•
•
•
Typy sterowników JDBC
JDBC-ODBC bridge driver – wsparcie usunięte w Java 8!
Java + Native code driver
All Java + Middleware translation driver
All Java driver – jest to jedyny obecnie wspierany typ sterownika.
Łączy aplikację bezpośrednio z bazą danych i jest specyficzny dla
poszczególnych serwerów. Jest też najbardziej efektywnym
(performance) rodzajem sterownika.
źródło: Jakob Jenkov
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Dalej zostały omówione typowe kroki spotykane w aplikacjach
wykorzystujących JDBC.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Załadowanie sterownika (od Java 6 automatycznie!)
Należy je wykonać raz. Przykładowy kod:
Class.forName("com.mysql.jdbc.Driver");
Korzystamy z mechanizmu refleksji ładując poprzez standardowego
class loader’a klasę sterownika określoną przez nazwę. Klasa ta zależy od
serwera bazy danych. Powyższy przykład ładuje sterownik JDBC serwera
MySQL.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Otwarcie połączenia z bazą danych
Wykorzystujemy klasę java.sql.DriverManager. Przykład dla MySQL:
String url = "jdbc:mysql://[host]:[port]/db_name";
String user = „uname";
String password = „passwd";
Connection connection = DriverManager.getConnection(url, user,
password);
[host] - jeśli pominięty, to localhost
[port] - domyślny port dla serwera MySQL, to 3306
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Jawne zamknięcie połączenia
Jeśli nie zamierzamy już korzystać z danego połączenia z bazą danych,
to powinniśmy je zamknąć w celu zwolnienia zasobów. Możemy to
wykonać za pomocą metody:
connection.close();
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Zapytania o dane (odczyt)
Jeśli mamy otwarte połączenie z bazą danych możemy skierować do
niej zapytanie w następujący sposób:
Statement statement = connection.createStatement();
String sql = "select * from people";
ResultSet result = statement.executeQuery(sql);
Wyniki zapytania zostają umieszczone w klasie ResultSet, którą
możemy iterować wierszami (rekordami):
while(result.next()) {
String name = result.getString("name");
long age = result.getLong ("age");
}
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Dla danego wiersza można uzyskać dostęp do danych w kolumnie za
pomocą jednej z metod:
getX()
gdzie:
X – klasa wrapera typu prostego
Dostęp do poszczególnych kolumn tabeli może być za pomocą nazwy
kolumny lub indeksu kolumny, co pokazano poniżej.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
getString(<column_name>);
getLong(<column_name>);
getInt(<column_name>);
getDouble(<column_name>);
getBigDecimal(<column_name>);
dr inż..Piotr Zabawa
Instytut Informatyki
getString(<column_index>);
getLong(<column_index>);
getInt(<column_index>);
getDouble(<column_index>);
getBigDecimal(<column_index>);
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Indeks kolumny w ramach ResultSet można uzyskać po nazwie za
pomocą wywołania następującej metody:
int columnIndex = result.findColumn("columnName");
Dostęp za pomocą indeksu jest szybszy.
Po skorzystaniu z wyników zapytania należy zwolnić zasoby:
result.close();
statement.close();
Można wywołania te umieścić w bloku finally.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
try(Statement statement = connection.createStatement()) {
String sql = "select * from people";
try(ResultSet result = statement.executeQuery(sql)) {
ResultSet result = statement.executeQuery(sql);
while(result.next()) {
String name = result.getString("name");
long age = result.getLong("age");
System.out.println(name);
System.out.println(age);
}
}
}
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Zapis do bazy
Są dwa rodzaje zapisów:
• Aktualizacja rekordu
• Usunięcie rekordu
Do wykonania obu rodzajów zapisu wykorzystywana jest metoda:
executeUpdate()
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Zmiana rekordów
Statement statement = connection.createStatement();
String sql = "update people set name='John' where id=123";
int rowsAffected = statement.executeUpdate(sql);
Metoda executeUpdate() zwraca informację o ilości zmienionych rekordów.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Usunięcie rekordów
Statement statement = connection.createStatement();
String sql = "delete from people where id=123";
int rowsAffected = statement.executeUpdate(sql);
Metoda executeUpdate() zwraca informację o ilości zmienionych
rekordów.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
ResultSet
Klasa ResultSet zawiera wynik zapytania. Można go sobie
wyobrazić jako tabelę z rekordami w wierszach i polami rekordów w
kolumnach. Należy pamiętać, że komórki tabeli mogą zawierać dane, a
niektóre wartość null reprezentująca brak danych (nie wszystkie pola w
tabeli relacyjnej bazy danych są wymagane).
Należy mieć na uwadze fakt, że nie można uzyskać w sposób
bezpośredni informacji o ilości wierszy w ResultSet.
•
Są dwa sposoby utworzenia obiektu tej klasy:
Przez wykonanie zapytania (Statement)
• Przez wykonanie przygotowanego zapytania
(PreparedStatement)
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Wykonanie Statement:
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery("select *
from people");
Wykonanie PreparedStatement:
String sql = "select * from people";
PreparedStatement statement = connection.prepareStatement(sql);
ResultSet result = statement.executeQuery();
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
W czasie tworzenia stwierdzenia możemy sterować następującymi
parametrami tworzonego przez niego obiektu klasy ResultSet:
•
•
•
Type
Concurrency
Holdability
Statement statement = connection.createStatement(
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_OVER_COMMIT );
PreparedStatement statement = connection.prepareStatement(sql,
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_OVER_COMMIT );
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Typy ResultSet
• ResultSet.TYPE_FORWARD_ONLY
Oznacza, że nie jest możliwe iterowanie w przeciwnym kierunku niż
od pierwszego do ostatniego rekordu. Jest domyślny.
• ResultSet.TYPE_SCROLL_INSENSITIVE
Można iterować w dowolnym kierunku i przeskakiwać do dowolnego
rekordu, ale zmiana danych w bazie danych nie zostanie odzwierciedlona
w obiekcie klasy ResultSet po jego utworzeniu.
• ResultSet.TYPE_SCROLL_SENSITIVE
Można iterować w dowolnym kierunku i przeskakiwać do dowolnego
rekordu. Zmiana danych w bazie danych zostanie odzwierciedlona w
obiekcie klasy ResultSet po jego utworzeniu.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Metody nawigacji
Dostępność poniżej przedstawionych metod zależy od serwera bazy
danych, sterownika JDBC oraz typu ResultSet.
Metoda
Opis
absolute()
Ustawia kursor we wskazanej pozycji względem początkowego rekordu
afterLast()
Ustawia kursor na końcu (poza zakresem)
beforeFirst()
Ustawia kursor na początku (poza zakresem)
first()
Ustawia kursor na pierwszy rekord
last()
Ustawia kursor na ostatni rekord
next()
Przesuwa kursor do następnej pozycji
previous()
Przesuwa kursor do poprzedniej pozycji
relative()
Przesuwa kursor z aktualnej pozycji o wskazaną ilość rekordów (+/-)
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Metody uzyskiwania informacji o aktualnej pozycji kursora
Metoda
Opis
getRow()
Zwraca numer wiersza dla aktualnej pozycji kursora
getType()
Zwraca informację o typie ResultSet
isAfterLast()
Zwraca true jeśli kursor wyszedł poza ostatni rekord
isBeforeFirst()
Zwraca true jeśli kursor jest przed pierwszym rekordem
isFirst()
Zwraca true jeśli kursor wskazuje na pierwszy rekord
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Metoda odświeżająca aktualny wiersz w ResultSet, jeśli ResultSet jest
typu ResultSet.TYPE_SCROLL_SENSITIVE
Metoda
Opis
refreshRow()
Aktualizuje wartości pól rekordu w ResultSet na podstawie
aktualnych wartości rekordu w bazie danych
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Współbieżność ResultSet
Dostępne są dwa poziomy współbieżności:
• ResultSet.CONCUR_READ_ONLY
• ResultSet.CONCUR_UPDATABLE
Jeśli ResultSet jest określony jako , to można dokonać aktualizacji
poszczególnych pól danego rekordu za pomocą metod updateX()
analogicznych do getX(). Do pól można odwoływać się po nazwie lub
po indeksie kolumny. Należy pamiętać o wywołaniu metody
result.updateRow() dla całego rekordu po aktualizacji jego pól.
Metoda ta dokonuje aktualizacji danych w bazie pod warunkiem, że nie
została wywołana wewnątrz transakcji. Przykłady metod updateX()
podano poniżej.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
updateString(<column_name>);
updateLong(<column_name>);
updateInt(<column_name>);
updateDouble(<column_name>);
updateBigDecimal(<column_name>);
dr inż..Piotr Zabawa
Instytut Informatyki
updateString(<column_index>);
updateLong(<column_index>);
updateInt(<column_index>);
updateDouble(<column_index>);
updateBigDecimal(<column_index>);
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Wstawianie wierszy do ResultSet
Aby wstawić wiersz do ResultSet należy wykonać następujące
kroki:
• Wywołać ResultSet.moveToInsertRow()
•
•
Zaktualizować wartości kolumn w tym wierszu
Wywołać ResultSet.insertRow()
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
ResultSet Holdability
Cecha ta określa czy po dokonaniu commitu obiektu ResultSet do bazy
danych następuje destrukcja obiektu ResultSet czy nie. Dostępność tej
funkcjonalności dla danego sterownika można sprawdzić wywołaniem
metody:
DatabaseMetaData.supportsResultSetHoldability(int holdability)
•
•
Rodzaje holdability:
ResultSet.CLOSE_CURSORS_OVER_COMMIT
ResultSet.HOLD_CURSORS_OVER_COMMIT
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
•
•
•
•
PreparedStatement
Powody stosowania:
Łatwość wprowadzania parametrów do zapytania SQL
Łatwość ponownego użycia z nowymi parametrami
Możliwość zwiększenia wydajności wykonywanych komend
Ułatwienie wykonywania batch updates.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Przykład:
String sql = "update people set firstname=? , lastname=? where id=?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "Gary");
preparedStatement.setString(2, "Larson");
preparedStatement.setLong (3, 123);
int rowsAffected = preparedStatement.executeUpdate();
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Zwiększenie efektywności zapytań:
• Poprzez cache’owanie zapytań po stronie sterownika
• Poprzez współdzielenie zapytań pomiędzy aplikacjami Java
• Poprzez cache’owanie zapytań po stronie serwera bazy danych –
zwiększenie wydajności poprzez minimalizację analizy planu wykonania
zapytań
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Batch Updates
Ten tryb pracy z bazą danych polega na przesyłaniu do niej wielu
komend za jednym razem. Nie ma sensu stosowanie go dla zapytań
(odczytu), lecz jedynie dla zapisu.
Można wykonywać takie update’y za pomocą:
• Statement
• PreparedStatement
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Statement
Statement statement = null;
try{
statement = connection.createStatement();
statement.addBatch("update people set firstname='John' where id=123");
statement.addBatch("update people set firstname='Eric' where id=456");
statement.addBatch("update people set firstname='May' where id=789");
int[] recordsAffected = statement.executeBatch();
} finally {
if(statement != null) statement.close();
}
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
PreparedStetment
String sql = "update people set firstname=? , lastname=? where id=?";
PreparedStatement preparedStatement = null;
try{
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "Gary");
preparedStatement.setString(2, "Larson");
preparedStatement.setLong (3, 123);
preparedStatement.addBatch();
preparedStatement.setString(1, "Stan");
preparedStatement.setString(2, "Lee");
preparedStatement.setLong (3, 456);
preparedStatement.addBatch();
int[] affectedRecords = preparedStatement.executeBatch();
} finally {
if(preparedStatement != null) preparedStatement.close();
}
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Ryzyko stosowania batch updates polega na tym, że część komend
może się udać, a część nie i wtedy nie wiadomo jak postąpić w kodzie.
Dlatego dobrą praktyką wykonywania batch updates jest wykonywanie
ich w ramach transakcji.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Transakcje
Służą określeniu, który zestaw operacji ma być traktowany łącznie
jako operacja atomowa. Jeśli wszystkie operacje składowe zakończą się
sukcesem, to zestaw operacji zostanie wykonany w całości. Jeśli któraś z
operacji składowych nie powiedzie się, to nie zostanie wykonana żadna z
operacji.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Przykład transakcji
Connection connection = ...
try {
connection.setAutoCommit(false);
// create and execute statements etc.
connection.commit();
} catch(Exception e) {
connection.rollback();
} finally {
if(connection != null) connection.close();
}
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Procedury składowane
Jest to rozwiązanie dostępne po stronie bazy danych. Służy do
przechowywania procedur zawierających komendy w celu zwiększenia
wydajności.
Utworzenie komendy:
CallableStatement callableStatement = connection.prepareCall("{call
calculateStatistics(?, ?)}");
albo
CallableStatement callableStatement =
connection.prepareCall("{call calculateStatistics(?, ?)}",
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_OVER_COMMIT );
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Java 7
• Dodano instrukcję try-with-resources w celu zautomatyzowania
zamykania zasobów znanego z wykładu dotyczącego wyjątków –
przykład z zamykaniem strumieni. Połączenie z bazą danych traktowane
jest jako zasób. Przykład na następnym slajdzie
• Dodano interfejs RowSetFactory i klasę RowSetProvider pozwalające
na uzyskanie każdego z rodzajów RowSet dostępnych dla danego JDBC
Driver, a więc uwzględniających specyfikę serwera bazy danych.
Przykład na kolejnym slajdzie
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Przykład:
public static void sampleQueryProc(Connection sampleCon) throws SQLException {
String sampleQuery = "select ROLLNO, NAME, ADDRESS from STUDENT";
try (Statement sampleStmt = sampleCon.createStatement()) {
ResultSet sampleResultSet = sampleStmt.executeQuery(sampleQuery);
while (rs.next()) {
int rollNo = sampleResultSet.getInt("ROLLNO");
String studentName = sampleResultSet.getString("NAME");
String studentAddress = sampleResultSet.getString("ADDRESS");
System.out.println(“ROLLNO:” + rollNo + " NAME: " + studentName + "
ADDRESS: " + studentAddress);
}
}
}
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
public void sampleMethod(String sampleUserName, String samplePassword)
throws SQLException {
RowSetFactory sampleRowSetFactory = null;
JdbcRowSet sampleRowSet = null;
try {
sampleRowSetFactory = RowSetProvider.newFactory();
sampleRowSet = sampleRowSetFactory.createJdbcRowSet();
sampleRowSet.setUrl("jdbc:sampleDriver:sampleAttribute");
sampleRowSet.setUsername(sampleUserName);
sampleRowSet.setPassword(samplePassword);
sampleRowSet.setCommand(""select ROLLNO, NAME, ADDRESS from STUDENT");
sampleRowSet.execute();
}
catch(Exception e) {
}
}
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Parametry wyjściowe z procedury składowanej
Procedura składowana może zwracać wartości. Przykład korzystania z
parametrów wyjściowych procedury składowanej podano na następnym
slajdzie.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
CallableStatement callableStatement =
connection.prepareCall("{call calculateStatistics(?, ?)}");
callableStatement.setString(1, "param1");
callableStatement.setInt (2, 123);
callableStatement.registerOutParameter(1, java.sql.Types.VARCHAR);
callableStatement.registerOutParameter(2, java.sql.Types.INTEGER);
ResultSet result = callableStatement.executeQuery();
// najpierw ResultSet
while(result.next()) { ... }
// potem OUT parameters
String out1 = callableStatement.getString(1);
int out2 = callableStatement.getInt (2);
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Należy najpierw analizować ResultSet, a dopiero potem parametry
wyjściowe – dobra praktyka związana z kompatybilnością z różnymi
serwerami bazodanowymi.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
DatabaseMetaData
Metody z tej grupy służą uzyskaniu ogólnych informacji o bazie
danych.
Uzyskanie obiektu meta-danych:
DatabaseMetaData databaseMetaData = connection.getMetaData();
Uzyskanie danych o serwerze bazodanowym:
int majorVersion = databaseMetaData.getDatabaseMajorVersion();
int minorVersion = databaseMetaData.getDatabaseMinorVersion();
String productName = databaseMetaData.getDatabaseProductName();
String productVersion = databaseMetaData.getDatabaseProductVersion();
Uzyskanie danych o sterowniku:
int driverMajorVersion = databaseMetaData.getDriverMajorVersion();
int driverMinorVersion = databaseMetaData.getDriverMinorVersion();
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Wylistowanie tabel:
String catalog = null;
String schemaPattern = null;
String tableNamePattern = null;
String[] types = null;
ResultSet result = databaseMetaData.getTables( catalog, schemaPattern,
tableNamePattern, types );
while(result.next()) { String tableName = result.getString(3); }
Wylistowanie kolumn w tabeli:
String catalog = null;
String schemaPattern = null;
String tableNamePattern = "my_table";
String columnNamePattern = null;
ResultSet result = databaseMetaData.getColumns( catalog, schemaPattern,
tableNamePattern, columnNamePattern);
while(result.next()){
String columnName = result.getString(4);
int columnType = result.getInt(5);
}
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Uzyskanie informacji o kluczu prywatnym tabeli
String catalog = null;
String schema = null;
String tableName = "my_table";
ResultSet result = databaseMetaData.getPrimaryKeys( catalog, schema,
tableName);
while(result.next()) String columnName = result.getString(4);
Dla kluczy złożonych zwrócony ResultSet może mieć wiele
wierszy.
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Sprawdzanie jakie funkcjonalności są wspierane przez dany sterownik
databaseMetaData.supportsGetGeneratedKeys();
databaseMetaData.supportsGroupBy();
databaseMetaData.supportsOuterJoins();
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java - JDBC
Ustawianie wartości parametrów wywołania metody składowanej:
callableStatement.setString(1, "param1");
callableStatement.setInt (2, 123);
Wykonanie metody składowanej:
ResultSet result = callableStatement.executeQuery();
albo
callableStatement.executeUpdate();
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Trwałość w Java – 10 dobrych praktyk
JDBC
•
•
•
•
•
•
•
•
•
•
Stosować PreparedStatement
Stosować ConnectionPool
Wyłączać tryb auto commit
Stosować JDBC Batch Update
W dostępie do ResultSet stosować nazwy kolumn aby uniknąć wyjątku
invalidColumIndexError
Stosować zmienne Bind zamiast konkatenacji String’ów
Zawsze zamykać Statement, PreparedStatement i Connection
Wybierać odpowiedni sterownik JDBC dla tworzonej aplikacji
Stosować standardowe zapytania i unikać stosowania wyrażeń specyficznych
dla serwera bazy danych o ile to możliwe
Stosować właściwą metodę getXXX()
dr inż..Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Koniec
dr inż. Piotr Zabawa
Instytut Informatyki
Wydział Fizyki, Matematyki i Informatyki

Podobne dokumenty