notatki java 05

background image

Plan wykładu

1. Zaawansowane możliwości JDBC:

rodzaje obiektów

ResultSet

,

dodatkowe możliwości obiektów

ResultSet

,

zapytania prekompilowane,

wywoływanie zdalnych procedur,

transakcje.

2. Przegląd wybranych systemów bazodanowych:

HSQLDB.

1

background image

Rodzaje obiektów ResultSet

Ze względu na dostęp do odebranych danych obiekty

ResultSet

dzielimy na:

TYPE_FORWARD_ONLY

– odbiór danych kolejno od pierwszego do ostatniego

rekordu,

TYPE_SCROLL_INSENSITIVE

– dostęp do dowolnych danych, przygotowane

wyniki nie zmieniają sie pod wpływem zmian w bazie.

TYPE_SCROLL_SENSITIVE

– dostęp do dowolnych danych, przygotowane wyniki

zmieniają sie pod wpływem zmian w bazie. Kolejność rekordów nie musi być stała.

Rodzaj dostępu zmieniamy metodą

setFetchDirection(int)

. Do przechodzenia

między rekordami służą metody:

next()

,

previous()

,

last()

,

first()

,

absolute()

,

relative()

.

2

background image

Rodzaje obiektów ResultSet

Obiekty

ResultSet

mogą mieć różne możliwości zmieniana odebranych danych:

1.

CONCUR_READ_ONLY

– dane nie mogą być zmienione poprzez metody

updateXXX()

.

najwyższy poziom współbieżności (największa liczba użytkowników jednocześnie

operujących na danych

Jedyna możliwość w wersji JDBC 1.0

2.

CONCUR_UPDATABLE

– dane mogą być zmieniane.

zmniejszony poziom współbieżności,

mniejsza wydajność.

3

background image

Rodzaje obiektów ResultSet

Connection con = DriverManager.getConnection(

"jdbc:my_subprotocol:my_subname");

Statement stmt = con.createStatement(

ResultSet.TYPE_SCROLL_SENSITIVE,

ResultSet.CONCUR_UPDATABLE,

ResultSet.HOLD_CURSORS_OVER_COMMIT);

stmt.setFetchSize(25);

ResultSet rs = stmt.executeQuery(

"SELECT col1, col2 FROM table1");

Obiekt

rs

udostępnia dane w dowolnej kolejności, umożliwia zmianę danych, nie

jest zamykany przy zatwierdzeniu transakcji. Do bazy danych zostaje przekazana

sugestia, aby dane odbierać w pakietach po 25 rekordów.

4

background image

Inne operacje na obiektach ResultSet

1. Usuwanie rekordów:

rs.first();

rs.deleteRow();

2. Wstawianie rekordów:

rs.moveToInsertRow();

rs.updateObject(1, myArray);

rs.updateInt(2, 3857);

rs.updateString(3, "Mysteries");

rs.insertRow();

rs.first();

5

background image

Inne operacje na obiektach ResultSet

Uwagi do wstawiania rekordów:

1. Na wstawianym rekordzie można wywoływać metody

getXXX()

. Jeśli

odpowiednia wartość nie została ustawiona wcześniej metodą

updateXXX()

wartość zwracana będzie nieokreślona.

2. Aktualizacja wartości we wstawianym rekordzie nie zmienia obiektu

ResultSet

.

3. metoda

insertRow()

, dodająca rekord do obiektu

ResultSet

i do bazy danych

zrzuca

SQLException

, jeśli liczba lub typy kolumn nie zgadzają się ze specyfikacją

tabeli w bazie.

4. Bieżącym rekordem jest ten, który był nim przed wywołaniem metody

moveToInsertRow()

.

6

background image

Inne operacje na obiektach ResultSet

Odczytywanie dużych porcji danych:

Statement stmt = con.createStatement();

ResultSet rs = stmt.executeQuery("SELECT xdata FROM Table2");

byte [] buff = new byte[4096];

while (rs.next()) {

InputStream fin = rs.getAsciiStream(1);

for (;;) {

int size = fin.read(buff);

if (size == -1) break;

// wypisanie danych

System.out.write(buff, 0, size);

}

}

7

background image

Prekompilowane zapytania

JDBC przewiduje możliwość tworzenia prekompilowanych zapytań. Służy do tego

klasa

PreparedStatement

wyprowadzona z klasy

Statement

. Przykłady:

PreparedStatement pstmt = con.prepareStatement(

"UPDATE table4 SET m = ? WHERE x =
?");

PreparedStatement pstmt2 = con.prepareStatement(

"SELECT a, b, c FROM Table1",
ResultSet.TYPE_SCROLL_SENSITIVE,

ResultSet.CONCUR_UPDATABLE);

ResultSet rs = pstmt2.executeQuery();

Używanie prekompilowanych zapytań może zwiększyć szybkość działania

programu.

8

background image

Przekazywanie parametrów

Przekazywanie parametrów:

pstmt.setString(1, "Hi");

for (int i = 0; i < 10; i++) {

pstmt.setInt(2, i);

int rowCount = pstmt.executeUpdate();

}

Od wersji JDBC 2.0 można przekazywać parametry typu

SQL BLOB

oraz

SQL

ARRAY

.

PreparedStatement pstmt = con.prepareStatement(

"UPDATE Table3 SET Stats = ? WHERE Depts = ?");

pstmt.setBlob(1, statistics);

pstmt.setArray(2, departments);

9

background image

Przekazywanie dużych parametrów

Przykład pokazuje jak przesłać zawartość pliku jako parametr wejściowy:

File file = new File("/tmp/data");

int fileLength = file.length();

InputStream fin = new FileInputStream(file);

PreparedStatement pstmt = con.prepareStatement(

"UPDATE Table5 SET stuff = ? WHERE index = 4");

pstmt.setBinaryStream (1, fin, fileLength);

pstmt.executeUpdate();

Inny sposób polega na wykorzystaniu typów BLOB i CLOB.

10

background image

Informacje o parametrach

Dodatkowe dane o parametrach prekompilowanego zapytania można uzyskać

poprzez interfejs

ParameterMetaData

(JDBC 3.0):

PreparedStatement pstmt = con.prepareStatement(

"INSERT INTO QUOTAS (ID, LAST, FIRST, DEPT, QUOTA) " +

"VALUES (?, ?, ?, ?, ?)";

ParameterMetaData paramInfo = pstmt.getParameterMetaData();

int numberOfParams = paramInfo.getParameterCount();

for (int i = 1; i <= numberOfParams; i++) {

String dbType = paramInfo.getParameterTypeName(i);

System.out.println("Param " + i " is DBMS type " + dbType);

}

11

background image

Serie prekompilowanych zapytań

Podobnie jak w przypadku

Statement

istnieje możliwość przesłania serii zapytań.

PreparedStatement pstmt = con.prepareStatement(

"UPDATE Table4 SET History = ? WHERE ID = ?");

pstmt.setClob(1, clob1);

pstmt.setLong(2, 350985839);

pstmt.addBatch();

pstmt.setClob(1, clob2);

pstmt.setLong(2, 350985840);

pstmt.addBatch();

int [] updateCounts = pstmt.executeBatch();

Jeśli którekolwiek z zapytań

UPDATE

zwróci cokolwiek ponad liczbę zmienionych

rekordów metoda

executeBatch()

zrzuci wyjątek.

12

background image

Zdalne procedury

Do wywoływania zdalnych procedur używa się obiektów klasy

CallableStatement

:

CallableStatement cstmt = con.prepareCall(

"{call updatePrices(?, ?)}");

cstmt.setString(1, "Colombian");

cstmt.setFloat(2, 8.49f);

cstmt.addBatch();

cstmt.setString(1, "Colombian_Decaf");

cstmt.setFloat(2, 9.49f);

cstmt.addBatch();

int [] updateCounts = cstmt.executeBatch();

Procedura zostanie wywołana dwukrotnie Parametry przekazywane do procedury

nazywamy parametrami IN.

13

background image

Zdalne procedury – odbieranie wyników

Istnieje możliwość ustawienia parametrów przez zdalną procedurę (parametry OUT):

CallableStatement cstmt = con.prepareCall(

"{call getTestData(?, ?)}");

cstmt.registerOutParameter(1, java.sql.Types.TINYINT);

cstmt.registerOutParameter(2, java.sql.Types.DECIMAL);

ResultSet rs = cstmt.executeQuery();

// ... odczyt danych poprzez ResultSet

byte x = cstmt.getByte(1); // odczyt zwracanych parametrow

BigDecimal n = cstmt.getBigDecimal(2);

Procedura wypełnia przekazywane parametry.

14

background image

Zdalne procedury – odbieranie wyników

Numeracja parametrów OUT:

CallableStatement cstmt = con.prepareCall(

"{call getTestData(25, ?)}");

cstmt.registerOutParameter(1, java.sql.Types.TINYINT);

Przy numeracji uwzględniane są tylko parametry oznaczone znakiem zapytania

15

background image

Zdalne procedury – parametry INOUT

Parametry INOUT to takie, które są przekazywane do procedury a następnie

modyfikowane przez wywołaną procedurę.

CallableStatement cstmt = con.prepareCall(

"{call reviseTotal(?)}");

cstmt.setByte(1, (byte)25);

cstmt.registerOutParameter(1, java.sql.Types.TINYINT);

cstmt.executeUpdate();

byte x = cstmt.getByte(1);

Parametr jest najpierw ustawiany – IN a następnie rejestrowany jako OUT. Po

wywołaniu procedury można odebrać jego nową wartość. Zaleca się odebranie

wszystkich danych poprzez obiekt

ResultSet

przed

odebraniem parametrów

INOUT.

16

background image

Transakcje

Transakcje to zbiór operacji zgrupowanych w jednym lub wielu obiektach

Statement

. Aby zakończyć transakcję należy wywołać metodę

commit()

na rzecz

obiuektu

Connection

. Domyślnie metoda

commit()

jest wywoływana po

zakończeniu wykonywania zapytań w ramach jednego obiektu

Statement

. Aby to

zmienić należy użyć metody

setAutoCommit(false)

. Do anulowania zmian

wprowadzonych przez niezatwierdzoną transakcję służy metoda

rollback()

.

17

background image

Poziomy izolacji

Zwykle w systemy baz danych realizują jednocześnie wiele transakcji. Aby

zapewnić kontrolę nad tym procesem wprowadzono tzw. poziomy izolacji, poprzez

które określa się zasady równoległej realizacji kilku transakcji. JDBC przewiduje

pięć poziomów izolacji:

TRANSACTION_NONE

– brak transakcji.

TRANSACTION_READ_UNCOMMITTED

– dopuszcza odczyt danych przed

wywołaniem metody

commit()

.

TRANSACTION_READ_COMMITTED

– inne transakcje nie mogą odczytywać

zmienionych wierszy przed wywołaniem metody

commit()

(dirty reads).

18

background image

Poziomy izolacji

TRANSACTION_REPEATABLE_READ

– dodatkowo chroni przed sytuacją gdy

transakcja odczytuje wiersz, druga transakcja go zmienia a pierwsza ponownie go

odczytuje otrzymując inne dane (non-repetable reads).

TRANSACTION_SERIALIZABLE

– dodatkowo chroni przed sytuacją, gdy jedna

transakcja odczytuje zbiór wierszy spełniający kryteria zawarte w warunku

WHERE

,

następnie druga transakcja wstawia wiersz spełniający ten warunek, po czym

pierwsza transakcja ponownie odczytuje zbiór wierszy dostając nowy rekord

(phantom-read).

Poziomy izolacji ustawia się metodą

setTransactionIsolation(int)

wywołaną na rzecz obiektu klasy

Connection

.

19

background image

Etapy transakcji - Savepoints

Obiekt

Savepoint

(JDBC 3.0) umożliwia częściowe odwrócenie (rollback)

transakcji zamiast całkowitego. Do utworzenia tego obiektu służy metoda

setSavepoint()

.

Statement stmt = con.createStatement();

int rows = stmt.executeUpdate("INSERT INTO AUTHORS VALUES " +

"(LAST, FIRST, HOME) 'TOLSTOY', 'LEO', 'RUSSIA'");

Savepoint save1 = con.setSavepoint("SAVEPOINT_1");

int rows = stmt.executeUpdate("INSERT INTO AUTHORS VALUES " +

"(LAST, FIRST, HOME) 'MELVOY', 'HAROLD', 'FOOLAND'");

...

con.rollback(save1);

...

con.commit();

20

background image

Zewnętrzne bazy danych

Interfejs JDBC jest dostarczany wraz z większością znanych systemów

bazodanowych. W dalszej części wykładu zostaną zaprezentowane dwa przykłady

systemów baz danych od strony ich wykorzystania z programami w języku Java.

Pierwszy z nich to natywna baza danych dla Javy : HSQLDB, drugi to jedna z

najpowszechniej stosowanych baz danych w małych i średnich projektach: MySQL.

21

background image

HSQLDB

22

HSQLDB to system baz danych w całości napisany w Javie (open source)..

Strona domowa projektu: http://www.hsqldb.org.

Niektóre własności:

obsługa SQL'a,

transakcje (COMMIT, ROLLBACK, SAVEPOINT),

integralność relacji (klucze obce), operacje kaskadowe,

zdalne procedury i funkcje (pisane w Javie),

triggery,

możliwość dołączania do programów i appletów. Działanie w trybie read-only,

tabele o rozmiarze do 8GB,

rozmiar tekstowych i binarnych danych ograniczony przez rozmiar pamięci.

background image

HSQLDB – tryby pracy serwera

23

Hsqldb Server – tryb preferowany. Klasa

org.hsqldb.Server

,

Hsqldb Web Server – używany, jeśli serwer może używać tylko

protokołu

HTTP

lub HTTPS. W przeciwnym razie niezalecany. Klasa

org.hsqldb.WebServer

,

Hsqldb Servlet – używa tego samego protokołu co Web Server. Wymaga osobnego

kontenera serwletów (np. Tomcat). Może udostępniać tylko jedną bazę danych.

Wszystkie tryby pracy serwera umożliwiają korzystanie z JDBC.

background image

HSQLDB – połączenie z serwerem

24

Przykład:

try {

Class.forName("org.hsqldb.jdbcDriver").newInstance();

} catch (Exception e) {

System.out.println("ERROR");

e.printStackTrace();

return;

}

Connection c = DriverManager.getConnection(

"jdbc:hsqldb:hsql://localhost/xdb", "sa", "");

Serwer:

localhost

, nazwa bazy:

xdb

, użytkownik:

sa

, hasło:

''

.

background image

HSQLDB – tryb stand-alone

25

W trybie stand-alone „serwer” bazy danych działa w ramach tej samej wirtualnej

maszyny Javy, co korzystający z niego program „kliencki”. Przykład uruchomienia

bazy:

Connection c = DriverManager.getConnection(

"jdbc:hsqldb:file:/opt/db/testdb", "sa", "");

Niewielkie bazy danych mogą być uruchamiane do pracy w pamięci operacyjnej

komputera:

Connection c = DriverManager.getConnection(

"jdbc:hsqldb:mem:testdb", "sa", "");

W obecnej wersji HSQLDB istnieje możliwość jednoczesnego używania wielu

„serwerów” baz danych działających w trybie stand-alone.

background image

HSQLDB – kończenie pracy z bazą

26

Wszystkie bazy mogą być zamknięte komendą SQL

SHUTDOWN

. Parametr połączenia

shutdown=true

wymusza „zamknięcie” bazy danych wraz z zakończeniem

ostatniego połączenia za pomocą metody

close()

.

Po komendzie

SHUTDOWN

wszystkie aktywne transakcje są anulowane (rollback)

Komenda

SHUTDOWN COMPACT

dodatkowo przepisuje pliki .data zmniejszając ich

rozmiar.

background image

Podsumowanie

27

Korzystanie z interfejsu JDBC umożliwia jednolity sposób dostępu do różnych

systemów bazodanowych. Jako przykład przedstawiono bazę HSQLDB. Jej ważną

zaletą jest możliwość działania w ramach jednej Wirtualnej Maszyny Javy wraz z

programem klienckim.


Wyszukiwarka

Podobne podstrony:
notatki java 08
notatki java 07
JAVA 05 operatory
Java 05 Klasy(1)
Java 05 Klasy
notatki java 04
java 05
notatki java 09
Moje Notatki Wykłady 05 11 2011
notatki java 10
notatki java 08
notatki java 07

więcej podobnych podstron