Sterownik JDBC i obsługa relacyjnych baz danych w Javie

Slides:



Advertisements
Podobne prezentacje
Programowanie sieciowe w Javie
Advertisements

Wstęp do strumieni danych
C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 4 ( ) Przeciążanie operatorów.
Procedury wyzwalane Procedura wyzwalana (ang. trigger) - stanowi kod użytkownika przechowywany wewnątrz bazy i uruchamiany w określonych sytuacjach np.
SQL INJECTION Wykorzystanie błędów w językach skryptowych
XML + relacyjne bazy danych
Java i bazy danych Programowanie z wykorzystaniem JDBC mgr inż. Piotr Kopniak.
Bazy danych II Instrukcja SELECT Piotr Górczyński 25/08/2001.
18/11/ Języki programowania 1 Piotr Górczyński Biblioteki.
Relacyjne Bazy Danych wykład XIII
Komponenty bazy danych Baza danych Jest to uporządkowany zbiór powiązanych ze sobą danych charakterystycznych dla pewnej klasy obiektów lub zdarzeń,
WPROWADZENIE DO BAZ DANYCH
Marcin Pamuła Mateusz Stefek
25/08/ Bazy danych II Piotr Górczyński MS Access – Action Query.
Kwerendy –wszystkie typy (usuwające, aktualizujące i inne)
20/09/ Języki programowania 1 Piotr Górczyński Kreator form.
18/11/ Języki programowania 1 Piotr Górczyński Łączenie z bazą danych.
Uniwersytet Łódzki Wydział Matematyki i Informatyki, Katedra Analizy Nieliniowej JDBC Database Access Wykład 12 mgr inż. Michał Misiak.
Inżynieria oprogramowania Lecture XXX JavaTM – część IV: IO
Zaawansowane technologie Javy Wykład 3 (21 lutego 2012) JDBC – programowanie bazodanowe (2)
Wykład 8 Wojciech Pieprzyca
Wykład 5 Wojciech Pieprzyca
Programowanie wizualne PW – LAB5 Wojciech Pieprzyca.
Wzorce projektowe w J2EE
Rozproszone bazy danych
PHP wprowadzenie.
Modele baz danych - spojrzenie na poziom fizyczny
PROJEKTOWANIE TABEL W PROGRAMIE: ACCESS
Terminy bazodanowe Tabela (relacja) Wiersz (krotka, rekord)
Wprowadzenie do JSP Copyright © Politecnico di Milano September 2003 Translation: Kamil Żyła, Politechnika Lubelska.
MySQL – ODBC - ACCESS.
Transakcje zarządzane kontenerem
dr hab. Ryszard Walkowiak prof. nadzw.
ANNA BANIEWSKA SYLWIA FILUŚ
Bazy danych podstawowe pojęcia
Bazy danych.
ASP BAZY. 2.2 S. Wolek Wst. do Inf. Połączenie z bazą danych przez ADO (ActiveX Data Object) do: - źródła ODBC - bazy z podanie nazwy sterownika ODBC.
SQL - Structured Query Language
JAVA.
Maszyna wirtualna ang. virtual machine, VM.
Aplikacje bazodanowe ADO.NET PHP i MySQL
Wybrane zagadnienia relacyjnych baz danych
Przekazywanie parametrów do funkcji oraz zmienne globalne i lokalne
Komendy SQL do pracy z tabelami i bazami
MICROSOFT Access TWORZENIE MAKR
18/11/ Języki programowania 1 Piotr Górczyński Kontrolki.
Zpiratował Rafał Kaczyński. Jest to technologia pozwalająca mapować dane obiektowe na odpowiadające im struktury w bazach danych. Hibernate pozwala na.
Bazy danych Microsoft access 2007.
PL/SQL – dalsza wędrówka
Autor: Damian Urbańczyk
Slajd 1© J.Rumiński Jacek Rumiński  Bazy danych Kontakt: Katedra Inżynierii Biomedycznej, pk. 106, tel.: , fax: ,
Jak wykonać prosty licznik odwiedzin strony internetowej?
Komendy SQL do pracy z danymi
Informatyka Stosowana – ROK II / III
Połączenie JSP z MS SQL Server 2000 Łukasz Sak Tomasz Raciborski.
.NET i Bazy Danych Projekt: Wadim Grasza.
Łukasz Bieszczad Mateusz Gałązka Karol Włodarek
BAZY DANYCH MS Access.
Współpraca PHP i MySQL Wygodniejszym i wydajniejszym sposobem przechowywania i korzystania z danych zapisanych na serwerze jest współpraca z relacyjna.
ASP.NET Kontrolki źródła danych i prezentacji danych w ASP.Net
ASP.NET Dostęp do bazy danych z poziomu kodu Elżbieta Mrówka-Matejewska.
Temat: Tworzenie bazy danych
Zaawansowane technologie Javy Wykład 7 (6 kwietnia 2017)
Programowanie Obiektowe – Wykład 2
Strukturalny język zapytań SQL - historia
Technologie Informacyjne Bazy danych
Czym są i jak służą społeczeństwu?
Modele baz danych - spojrzenie na poziom fizyczny
Zapis prezentacji:

Sterownik JDBC i obsługa relacyjnych baz danych w Javie Mariusz Czarneki, Marcin Walewski

JDBC Profesjonalne systemy bazodanowe udostępniają interfejsy programistyczne (API), dzięki którym można uzyskiwać dostęp do baz danych. Interfejsy takie są zdefiniowane dla różnych popularnych języków programowania na różne platformy systemowe. Programistyczny interfejs dostępu do baz danych z poziomu Javy to JDBC (ang. Java Database Connectivity API). JDBC jest uniwersalny i nie zależny od: maszyny bazodanowej, platformy sprzętowej, systemu operacyjnego.

JDBC (2) JDBC to zestaw klas i interfejsów umieszczonych w pakiecie java.sql, który umożliwia: połączenie z relacyjną bazą danych, wykonywanie instrukcji SQL na bazie, przetwarzanie wyników instrukcji SQL (w tym tabel wynikowych). Zadaniem JDBC jest ukrycie przed programistą wszelkich specyficznych właściwości określonej bazy danych. Najnowsza wersja JDBC to 4.1.

Przykładowe architektury JDBC Architektura dwuwarstwowa Architektura trójwarstwowa Przeglądarka Maszyna klienta (GUI) Aplikacja Java JDBC Maszyna klienta HTML, RMI, CORBA, Web Services Serwer Aplikacyjny Java JDBC Maszyna z logiką biznesową Właściwy protokół DBMS Właściwy protokół DBMS Serwer bazodanowy Serwer bazodanowy

Struktura JDBC java.sql.Driver to interfejs odpowiedzialny za nawiązanie połączenia z bazą danych oraz za tłumaczenie zapytań SQLowych na język określonej bazy. java.sql.DriverManager to klasa, która odpowiada za zarządzanie listą dostępnych sterowników do baz danych i udostępnienie aplikacji tego jednego, który jest przez nią wymagany. java.sql.Connection to interfejs, który reprezentuje pojedynczą transakcję bazodanową. java.sql.Statement jest to interfejs reprezentujący zapytanie SQLowe. java.sql.ResultSet to interfejs reprezentujący zbiór rekordów, będących wynikiem zapytania SQLowego; wynik zapytania znajduje się po stronie bazy danych.

4 typy sterowników TYP 1 – sterowniki, które implementują JDBC API mapując do innego API bazodanowego np. ODBC. Sterowniki te są zależne od bibliotek natywnych, które ograniczają przenośność. Przykładem jest JDBC-ODBC Bridge. TYP 2 – sterowniki pisane są częściowo w Javie z kodem natywnym. Te sterowniki wykorzystują natywne biblioteki klienta specyficzne dla danego źródła danych. Z powodu natywnego kodu przenośność ograniczona. TYP 3 – sterowniki napisane w pełni w Javie, które komunikują się przez warstwę pośredniczącą z serwerem korzystając z niezależnych od bazy danych protokołów. TYP 4 – sterowniki, które napisane są w pełni w Javie i implementują specyficzny dla danej bazy danych protokół. Klient łączy się bezpośrednio ze źródłem danych.

Pliki JAR zawierające sterownik do RDBMS Program w javie musi zarejestrować klasę sterownika JDBC. Automatyczna rejestracja jest wymagana dla sterowników zgodnych z JDBC4. W starszych wersjach trzeba ręcznie dokonać rejestracji: poprzez załadownie sterownika do pamięci: Class.forName(”org.postgresql.Driver”); albo przez skonfigurowanie właściwości jdbc.drivers przy uruchamianiu programu: java –Djdbc.drivers=org.postgresql.Driver Program sama aplikacja też może skonfigurować tą właściwość: System.setProperty(”jdbc.drivers”, ”org.postgresql.Driver”);

Ustanowienie połączenia ze źródłem danych Do połączenia z bazą danych wykorzystywane są dwa mechanizmy: DriverManager – wymaga, aby aplikacja załadowała odpowiedni sterownik JDBC korzystając z umieszczonego na stałe w kodzie adresu URL. Początkowo próbuje załadować sterownik wyszczególniony w property jdbc.drivers. DataSource – interfejs wykorzystywany przez DriverManager pozwalający zapewnić przeźroczystość źródła danych dla aplikacji. DataSource reprezentuje szczególne źródło danych.

Ustanowienie połączenia z źródłem danych – DriverManager Załadowanie sterowników. Class.forName("org.apache.derby.jdbc.XXXXDriver"); Class.forName – tworzy instancję sterowników XXXX (np. Oracle) i rejestruje je w DriverManager Korzystanie z DriverManager Zadaniem DriverManager jest rozpoznanie na podstawie URL rodzaju sterownika oraz jego odnalezieniu. jdbc:XXXX:<NazwaBazyDanych>[lista_wlasciwosci] Connection conn = DriverManager.getConnection("jdbc:XXXX:BazaDanych", login, pass); Połączenie z bazą należy na końcu zamknąć: try { if (conn!=null) conn.close(); } catch (SQLException ex) {/*…*/}

URL dla bazy danych URL dla bazy danych umożliwia identyfikację bazy, załadowanie odpowiedniego sterownika i uzyskanie połączenia z bazą. Składnia URLa używanego w JDBC: jdbc:<subprtokół>:<subnazwa> gdzie <subprtokół> to nazwa sterownika lub mechanizmu obsługi połączenia z bazą danych, a <subnazwa> to identyfikator bazy danych.

URL dla bazy danych (2) Przykład URLa dla połączenia z bazą zarejesrtowaną w ODBC: jdbc:odbc:moja_baza Przykłady URLi dla różnych systemów bazodanowych: MySQL: jdbc:mysql://localhost:3306/mydb MS-SQL: jdbc:sqlserver://127.0.0.1:1433/mydb PostgreSQL: jdbc:postgresql://serv:5432/mydb Mini-SQL: jdbc:msql://dbserver:1234/mydb Oracle: jdbc:oracle:thin:@localhost:1521:orcl Java-DB: jdbc:derby:newdb;create=true

Ustanawianie połączenia przez DataSource DataSource zwiększa przenaszalność aplikacji, gdyż aplikacja korzysta wyłączenie z nazwy źródła, bez wnikania w jego rodzaj. InitialContext ic = new InitialContext(); DataSource ds = ic.lookup("java:comp/env/jdbc/myDB"); Connection con = ds.getConnection(); DataSource ds = (DataSource) org.apache.derby.jdbc.ClientDataSource() ds.setPort(1527); ds.setHost("localhost"); ds.setUser("APP"); ds.setPassword("APP");

Metainformacje o bazie danych Metainformacje o bazie danych uzyskujemy za pomocą metody getMetaData: DatabaseMetaData md = conn.getMetaData(); W obiekcie DatabaseMetaData mamy cały zbiór metod do wyciągania informacji o bazie danych: getDatabaseProductName () getDriverName () getURL () getUserName () supportsTransactions () i wiele innych

Wyjątki SQL Często zdarza się, że jakaś operacja na bazie danych zakończy się niepowodzeniem – wtedy zgłaszany jest wyjątek: SQLException. Wyjątki te sygnalizują błędy, wykrywane albo przez sam sterownik (np. brak jakiegoś trybu działania), albo przez system bazodanowy (np. błędy składniowe w SQL lub próba naruszenia ograniczeń jednoznaczności czy spójności referencyjnej itp.) Wyjątki MUSIMY obsługiwać. W czasie operacji na bazie może zostać zgłoszonych kilka wyjątków – wyjątek SQLException potrafi się kolejkować.

Wyjątki SQL (2) Łapanie wyjątku SQLException na przykładzie: try { // operacje na bazie danych } catch (SQLException ex) { do { System.err.println(ex.getMessage()); } while ((ex=ex.getNextException())!=null); } Czasami pojawiają się tylko ostrzeżenia w postaci wyjątków SQLWarning dziedziczących po SQLException.

Czas na przykład = „ConnectionTest”

Wykonywanie zapytań do bazy – obiekt Statement Do wykonywania instrukcji SQL służy obiekt typu Statement, a także obiekty typu interfejsów pochodnych: PreparedStatement (prekompilowane instrukcje SQL), CallableStatement (przechowywane procedury). Obiektów tych nie tworzymy bezpośrednio, tylko uzyskujemy je od obiektu Connection za pomocą odwołań (odpowiednio): createStatement(…), prepareStatement(…), prepareCall(…). Statement stm = conn.createStatement(); Aby wykonać konkretne polecenie SQL, na rzecz obiektu typu Statement wywołujemy odpowiednie metody z argumentem typu String, kttóry jest poleceniem SQL.

Wykonywanie zapytań do bazy – obiekt Statement (2) Metody na rzecz obiektu Statement : stm.executeQuery(…); dla zapytania SELECT, zwraca tabelę wynikową. stm.executeUpdate(…); dla zapytań modyfikujących dane w bazie: CREATE TABLE…, DROP TABLE…, INSERT…, UPDATE…, DELETE…. zwraca liczbę zmodyfikowanych rekordów lub wartość -1, np. dla instrukcji CREATE. stm.execute(…); Wykonuje dowolną instrukcję SQL i zwraca wartość typu booolean – true, jeśli powstała tabela wynikowa, false, w przeciwnym przypadku. Wynik, będący tabelą wynikową lub liczbą zmodyfikowanych rekordów, uzyskujemy za pomocą dodatkowego odwołania do obiektu Statement. Ten sam obiekt typu Statement może być wielokrotnie używany do wykonywania różnych instrukcji SQL.

Drugi przykład – „DataBaseOperations”

Instrukcja SQL SELECT, tabele wynikowe i kursory W wyniku wykonania instrukcji SELECT powstaje tabela wynikowa. Jest ona w Javie dostępna poprzez obiekt typu ResultSet. ResultSet jest tworzony przez obiekt Statement po wykonaniu metody executeQuery albo execute z poleceniem SELECT. String query = "SELECT * FROM tabela;"; ResultSet rs = stm.executeQuery(query); Zasoby z danymi, do których odwołuje się ResultSet znajdują się po stronie systemu bazodanowego. Obiekt ResultSet reprezentuje tabelę rekordów z danymi. Dane z obiektu ResultSet odczytuje się, podobnie jak z pliku, za pomocą kursora, który przesuwa się nad kolejnymi rekordami w tabeli za pomocą metod next i previous. Kursor inicjalnie jest ustawiony przed pierwszym rekordem tabeli.

Obiekt ResultSet Przy tworzeniu obiektu Statement można określić jak będzie się zachowywać obiekt ResultSet: Statement stm = conn.createStatement(rsType, rsCon); przy czym oba argumenty createStatement są typu int, a odpowiadające im stałe są zdefiniowane w klasie ResultSet. Argument rsType [resultSetType] określa możliwości poruszania kursorem. Argument rsCon [resultSetConcurrency] określa możliwość równoczesnego wprowadzania zmian w tabelach.

Obiekt ResultSet (2) Argument rsType może przyjmować następujące wartości: ResultSet.TYPE_FORWARD_ONLY kursor można przesuwać tylko do przodu po jednym rekordzie; ResultSet.TYPE_SCROLL_INSENSITIVE kursor można dowolnie przesuwać, dane w tabeli nie są wrażliwe na równoczesne zmiany; ResultSet.TYPE_SCROLL_SENSITIVE kursor można dowolnie przesuwać, dane w tabeli są wrażliwe na równoczesne zmiany. Aby można było przemieszczać kursor w dowolnie wybrane pozycje należy wybrać jeden z typów TYPE_SCROLL_INSENSITIVE lub TYPE_SCROLL_SENSITIVE.

Obiekt ResultSet (3) Argument rsCon decyduje o możliwości modyfikowania danych w bazie i może przyjmować następujące wartości: ResultSet.CONCUR_READ_ONLY kursor możne tylko czytać dane z tabeli; ResultSet.CONCUR_UPDATABLE rekord, na który wskazuje kursor można dowolnie zmodyfikować i zmiany te będą zapamiętane w bazie danych. Przykład obiektu Statement, który może utworzyć ResultSet, w którym będzie można dowolnie przemieszczać kursor oraz modyfikować dane: Statement stm = conn.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);

Obiekt ResultSet (4) Obiekt Statement utworzony za pomocą: Statement stm = conn.createStatement(); może wygenerować obiekt ResultSet typu forward-only. Należy zamykać ResultSet po wykorzystaniu (rs.close()), aby zwolnić zasoby. ResultSet jest zamykany automatycznie, gdy zamykamy obiekt Statement lub gdy ten sam obiekt wykorzystywany jest ponownie do wykonania innej instrukcji SQL (powstaje wtedy nowy ResultSet).

Przemieszczanie kursora Interfejs ResultSet zawiera metody przemieszczające kursor, z których korzystamy przy przeglądaniu tabeli wynikowej. Metody przemieszczające kursor w obiekcie ResultSet: boolean next () boolean previous () boolean first () boolean last () boolean beforeFirst () boolean afterLast () boolean absolute (int n) boolean realtive (int n) Metody przemieszczające kursor w obiekcie ResultSet zwracają wartość boolowską true, gdy kursor ustawi się na jakimś rekordzie w tabeli albo false, gdy kursor wyskoczy poza tabelę. Rekordy w obiekcie ResultSet są numerowane od 1.

Przemieszczanie kursora (2) next() – przesuwa kurs do następnego wiersza. Jeśli wiersz jest ostatnim zwraca fałsz. previous() – przesuwa kurs jedną pozycje do tyłu. Zwraca fałsz jeśli kurs jest ustawiony na pierwszym wierszu. first() – przesuwa kurs na pierwsza pozycję. Zwraca fałsz jeśli ResultSet nie zawiera ani jednego wiersza. last() – przesuwa kurs do ostatniego wiersza w obiekcie ResultSet. Zwraca fałsz jeśli obiekt ResultSet nie zawiera żadnego wiersza. beforeFirst() – ustawia kursor na pozycję początkową przed pierwszym wierczem. afterLast() – przesuwa kurs na pozycję za ostatnim wierszem. relative(int rows) – przesuwa kursor do obecnej pozycji. absolute(int row) – pozycjonuje kursor na określonym wierszu.

Pobieranie wartości pól Do pobierania wartości z poszczególnych kolumn tabeli wynikowej służą metody getTTT(…) interfejsu ResultSet, które dokonują automatycznej konwersji pomiędzy typem pola definiowanym w SQL a typem Javy TTT (TTT oznacza tu jakiś typ np. int lub String). ResultSet rs=stmt.executeQuery(query); while (rs.next()) { TTT pole=rs.getTTT(column); } gdzie column to nazwa (String) lub numer kolumny (int).

Obsługa pól z wartością NULL Odczytując wartość pola numerycznego wskazywanego przez ResultSet metodą getInt możemy otrzymać wartość 0 lub -1 – wtedy nie wiemy, czy jest to wartość zapisana w tym polu czy może efekt przekształcenia null do typu int. Rozwiązaniem tego problemu jest metoda wasNull, która zwraca boolean i mówi nam czy ostatnio przeczytana wartość była null: int wiek = rs.getInt("wiek"); if (rs.wasNull()) {/*…*/} Innym rozwiązaniem jest użycie metody getObject: Integer wiek = (Integer)rs.getObject("wiek"); if (wiek==null) {/*…*/}

Modyfikowalna tabela wynikowa Jeżeli sterownik JDBC dopuszcza modyfikowalny ResultSet – typ ResultSet.CONCUR_UPDATABLE, możemy użyć wobec obiektu typu ResultSet metod updateTTT(…), updateRow(…), insertRow(…) deleteRow(…). Metody te pozwalają na dodawanie, modyfikowanie i usuwanie rekordów bez pośredniego użycia instrukcji SQL, operując na obiekcie RsultSet. Przed wywołaniem tych metod należy ustawić kursor, tak aby wskazywał odpowiedni rekord.

Modyfikowanie rekordów Metody modyfikujące dane w rekordzie pod kursorem w obiekcie ResultSet: void updateXxx (int col, Xxx val) void updateXxx (String col, Xxx val) void updateNull (int col) void updateNull (String col) void updateRow () Metody updateXxx modyfikują pole typu Xxx, na przykład updateInt, updateDouble, updateString. Pola w rekordzie są numerowane od 1. Metoda updateRow zapisuje zmienione wartości i musi być wywołana przed przejściem do następnego rekordu.

Wstawianie i usuwanie rekordów Metody wstawiające nowy rekord do tabeli w obiekcie ResultSet: void moveToInsertRow () void insertRow () boolean rowInserted () Metoda moveToInsertRow przesuwa kursor do miejsca, w którym będzie można zapisać nowy rekord. Po wypełnieniu rekordu danymi za pomocą metod updateXxx wstawiamy nowy rekord do tabeli metodą insertRow. Metody usuwające rekord pod kursorem w obiekcie ResultSet: void deleteRow () Metody deleteRow nie wolno używać w stosunku do nowowstawionego rekordu.

Metainformacje o tabeli wynikowej Metainformacje o tabeli wynikowej uzyskujemy za pomocą metody getMetaData: ResultSetMetaData rsmd = rs.getMetaData(); W obiekcie ResultSetMetaData mamy zbiór metod do wyciągania informacji o tabeli wynikowej: getcolumnCount () getColumnName (int n) getColumnDisplaySize (int n) getColumnType (int n) getColumnTypeName (int n) getColumnClassName (int n) i wiele innych

Zapytanie preinterpretowane W JDBC można tworzyć procedury parametryzowane, w których podaje się wzorzec ze znacznikami (pytajniki) zastępowanymi konkretnymi wartościami przed wywołaniem (obiekty typu PreparedStatement). Obiekt klasy PreparedStatement tworzymy podobnie jak Statement: PreparedStatement stmt = conn.prepareStatement(”…”); W parametrze mogą wystąpić znaki zapytania (numerowane od 1), które uzupełniamy odpowiednimi wartościami za pomocą metod setXxx (gdzie Xxx oznacza typ parametru, na przykład stmt.setString(nr,arg), stmt.setInt(nr,arg), itp); po wypełnieniu znaczników konkretnymi wartościami można wykonać polecenie (używając na przykład metody execute()).

Przygotowane wyrażenia Przygotowane wyrażania reprezentuje obiekt preparedStatement i wykorzystywany jest w przypadku częstego wykonywania tego samego zapytania na bazie danych Zaletą jest to, że wyrażanie zostało wcześniej skompilowane. Jest wymagana komplikacja przed zapytaniem do bazy danych, wysłany jest jedynie SQL. Przykład PreparedStatement updateSales = con.prepareStatement( "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?"); ... updateSales.setInt(1, 75); updateSales.executeUpdate():

Obsługa transakcji Obsługa transakcji jest w JDBC sterowana obiektem Connection. Przy tworzeniu połączenia włączany jest tryb auto-commit – każda pojedyncze wyrażenie jest wykonywane jako osobna transakcja. Aby samodzielnie sterować transakcjami trzeba właściwość auto-commit ustawić na false: conn.setAutoCommit(false); Po wykonaniu kilku poleceń na bazie możemy je zatwierdzić poleceniem commit albo anulować poleceniem rollback. Istnieje też metoda getAutoCommit, która informuje o trybie auto-commit obiektu Connection.