Bazy danych i inżynieria oprogramowania Wykład 13: Wprowadzenie do standardu ODMG, część 7: Wiązanie do Java Kazimierz Subieta Instytut Podstaw Informatyki PAN, Warszawa Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 1 Założenia wiązania do Java Wiązanie do Java jest oparte na zasadzie zgodnie z którą programista powinien odbierać całość wiązania jako pojedynczy język dla wyrażania jednocześnie operacji na bazie danych jak i operacji na ulotnych strukturach języka programowania. Ta zasada implikuje kilka dalszych konsekwencji: Programista ma do czynienia z pojedynczym, zunifikowanym systemem typów zarówno dla obiektów programistycznych (ulotnych) jak i dla obiektów bazy danych (trwałych). Wiązanie respektuje składnię języka Java (nie wprowadza dodatkowej składni). Wiązanie respektuje semantykę składowania obiektów języka Java, w szczególności automatyczne zbieranie nieużytków (garbage collection). Obiekt (trwały lub ulotny), do którego nie można dostać się z poprzez referencje staje się nieużytkiem. Referencje z trwałych obiektów mogą prowadzić wyłącznie do trwałych obiektów. Tę własność określa się jako trwałość poprzez osiągalność (persistence through reachability). K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 2 Sposoby deklarowania klas z obiektami trwałymi Istniejące klasy języka Java można zdefiniować jako klasy zdolne do trwałości (persistence-capable). Klasy zdolne do trwałości mogą mieć zarówno obiekty ulotne jak i trwałe. Istniejąca wersja standardu nie określa jednak, w jaki sposób można takie klasy powołać; ta własność jest uważana za cechę implementacyjną. Deklaracje klas Java (jak również schemat bazy danych) mogą być automatycznie wygenerowane przez preprocesor ODMG ODL. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 3 Model obiektowy ODMG w Java (1) Zdaniem autorów standardu ODMG, model obiektowy ODMG i model obiektowy Java są zbliżone. Niemniej ich różnice powodują, że wiązanie do Java nie podtrzymuje takich cech modelu obiektowego ODMG jak: związki, ekstensje, klucze, oraz dostęp do meta-schematu. Typ obiektu ODMG odwzorowuje się w typ obiektu Java. Podobnie, typy atomowych literałów ODMG odwzorowują się w równoważne typy prymitywne Java. Wiązanie nie przewiduje odwzorowania literałów strukturalnych. Definicja dowolnej struktury w modelu ODMG odwzorowuje się w definicję klasy w Java. Java przewiduje niezależne definicje interfejsów i implementacji. Interfejsy i klasy abstrakcyjne nie posiadają wystąpień i z tego powodu nie mogą być klasami zdolnymi do trwałości. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 4 Model obiektowy ODMG w Java (2) Kolekcje w ODMG posiadają metody zdefiniowane w ramach interfejsu Collection. Wiązanie do Java zakłada istnienie następujących interfejsów (i co najmniej jedną implementację) dla obsługi kolekcji: public interface Set extends Collection {...} public interface Bag extends Collection {...} public interface List extends Collection {...} Wprowadzony przez ODMG typ kolekcji Array odwzorowuje się w typ prymitywny array w Java, w klasę Vector, albo w specjalna klasę ODMG VArray, w zależności od potrzeby. Obiektom bazy danych mogą być przypisane nazwy poprzez zastosowanie metod zdefiniowanych w klasie Database w Java OML. Obsługa wyjątków zdefiniowanych w interfejsach ODMG jest określona przez standardowy mechanizm wyjątków Java. Zdefiniowano szereg specjalnych typów wyjątków. Przykłady typów wyjątków są następujące: TransactionAbortException (wyjątek powodowany przez zerwanie transakcji), ObjectNameNotUniqueException (próba nadania dla obiektu nazwy posiadanej przez inny obiekt), QueryParameterTypeInvalidException (wyjątek powodowany w sytuacji kiedy typ aktualnego parametru zapytania jest niezgodny z oczekiwanym), i inne. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 5 Java ODL Język Java ODL (Object Definition Language) służy do zapisu schematu bazy danych w postaci zbioru klas języka Java (z zachowaniem składni Java). Wystąpienia tych klas mogą być przetwarzane poprzez zestaw metod określany jako Java OML (Object Manipulation Language). Deklaracje atrybutów są identyczne do deklaracji pól w Java. Każdy typ elementarny z modelu ODMG jest odwzorowany w deklarację typu języka Java zgodnie z tabelą: Typ z ODMG modelu Long Short Unsigned long Float String Date Set Array Iterator .... Typ języka Java int(pry mityw), Integer (klasa) short (prymityw), Short (klasa) Long (pry mityw), long (klasa) float (pry mityw), Float (klasa) String java.sql.Date interface Set array type[] lub Vector Enu merat ion .... Czy może być literałem? tak tak tak tak tak nie nie nie nie .... Standard nie definiuje odwzorowań typu Enum (przeliczeniowego) oraz Interval (przedział). Deklaracja operacji w Java ODL są identyczne do deklaracji metod w Java. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 6 Java OML (1) Java OML (Object Manipulation Language) zawiera operacje do tworzenia obiektów, zmieniania wartości ich pól, oraz ich usuwania i identyfikacji. Daje też możliwość wywoływania metod. Przyjmuje się jako zasadę, że nie ma różnic w stosowaniu tych operacji do trwałych i ulotnych obiektów. Ponadto, pojedyncze wyrażenie może kombinować referencje do trwałych i ulotnych obiektów. ODMG wprowadza odstępstwa od zasady trwałości poprzez osiągalność. Wystąpienia klas, które nie są zdolne do trwałości, nigdy nie są trwałe, nawet jeżeli prowadzi do nich referencja z trwałego obiektu. W ramach trwałego obiektu można utworzyć nietrwały atrybut. Np.klasa Osoba może mieć nietrwały atrybut referencyjny bieżąceUwagi: public class Osoba { public String nazwisko; transient TypPewnegoObiektuUlotnego bieżąceUwagi; ...} Atrybut bieżąceUwagi nie będzie zapamiętywany w bazie danych. Podane reguły dotyczące trwałości są odbierane jako niekonsekwencja standardu lub plątanina pojęć. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 7 Java OML (2) Wiązanie do Java nie zakłada istnienia operacji usuwania obiektów. Obiekt przestaje istnieć w momencie, gdy nie posiada nazwy i nie prowadzi do niego żadna referencja z (osiągalnego) trwałego obiektu. Nieosiągalny obiekt jest automatycznie usuwany. Modyfikacje obiektów są widoczne w bazie danych dopiero po potwierdzeniu transakcji, w ramach której te modyfikacje się odbywają. Programy aplikacyjne używają nazw obiektów celem odwołania się do tzw. obiektówkorzeni (root objects), od których można rozpocząć nawigację w „pajęczynie” obiektów składających się na obiektową bazę danych. Nazwy obiektów bazy danych tworzą pojedynczą, płaską przestrzeń. Wszystkie nazwy w bazie danych są unikalne. Nazwa obiektu nie jest dostępna jako jego atrybut. Standard nie mówi nic o tym, czy atrybuty i związki również posiadają nazwy. W odróżnieniu od nazw obiektów, nazwy te są traktowane (prawdopodobnie) jako byty drugiej kategorii programistycznej, tj. istnieją wyłącznie w tekście programu. Atrybuty i związki są dostępne poprzez standardową składnię Java; obydwie kategorie są odwzorowane w Java jako zmienne polowe (field variables). Operacje są zdefiniowane w Java OML jako metody w Java. Operacje na obiektach ulotnych i trwałych zachowują się identycznie i mają identyczną pragmatykę użycia. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 8 Kolekcje Standard wprowadza interfejsy dla kolekcji: Collection, Set, Bag, List oraz Array. Obiektowa baza danych powinna definiować dowolną liczbę klas konkretnych implementujących różnorodne interfejsy dla kolekcji. public interface Collection { // Operacje modelu ODMG public int size(); // cardinality() public boolean IsEmpty(); // is_empty() public void add( Object obj ); // insert_element(...) public Object remove( Object obj ); // remove_element(...) public boolean contains( Object obj ); // contains_element(...) public Enumeration elements() // Iterator create_iterator(...) public Object selectElement( String predicate ); public Enumeration select( String predicate ); public Collection query( String predicate ); public boolean existsElement( String predicate ); } K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 9 Kolekcja Set public interface Set extends Collection { public Set union( Set otherSet ); public Set intersection( Set otherSet ); public Set difference( Set otherSet ); public boolean subsetOf( Set otherSet ); public boolean properSubsetOf( Set otherSet ); public boolean supersetOf( Set otherSet ); public boolean properSupersetOf( Set otherSet ); } // Operacje modelu ODMG // create_union(...) // create_intersection(...) // create_difference(...) // is_subset_of(...) // is_proper_subset_of(...) // is_superset_of(...) // is_proper_superset_of(...) Problem z kolekcjami polega na tym, że są one szablonami zawierającymi parametr. Nie jest pewne, czy mają one być pierwszej czy drugiej kategorii programistyznej. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 10 Transakcje Transakcje są zaimplementowane w Java OML jako obiekty klasy Transaction, zawierającej definicję takich metod jak: • Transaction (utworzenie nowej transakcji), • join (połączenie aktualnie wykonywanego wątku z pewną transakcją), • leave (odłączenie wykonywanego wątku od transakcji), • current (sprawdzenie, do której transakcji jest podłączony wykonywany wątek), • begin (uruchomienie transakcji; transakcje nie mogą być zagnieżdżane), • isOpen (sprawdzenie, czy transakcja jest uruchomiona), • commit (potwierdzenie transakcji), • abort (zerwanie transakcji), • checkpoint (potwierdzenie transakcji bez jej zakończenia i z zachowaniem zamków), • lock (podwyższenie statusu zamka założonego na dany obiekt przez transakcję) Zanim nastąpią operacje na bazie danych, dany wątek musi utworzyć transakcję lub połączyć się z istniejącą transakcją przy pomocy operacji join. Transakcja musi być następnie otwarta poprzez operację begin. Dalsze operacje danego wątku są wykonywane w ramach tej transakcji, aż do jej zakończenia lub zerwania. Dany wątek po otwarciu jednej transakcji nie może odwoływać się do żadnej innej transakcji. W obecnym standardzie transakcje nie dotyczą obiektów ulotnych. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 11 Java OQL (1) Autorzy standardu twierdzą, że wiązanie do Java zapewnia pełna funkcjonalność OQL. To twierdzenie jest mało wiarygodne ze względu na zasadnicze różnice koncepcyjne pomiędzy Java i OQL, powodujące ograniczenia i niewygody. Możliwości przetwarzania zapytań są zawarte w interfejsie Collection. Metody selectElement, select, query i existsElement posiadają stringowy argument predicate, który jest zapytaniem w OQL (ściślej, jest określony przez składnię klauzuli where). Np. metoda query może być użyta w sposób następujący: SetOfObject fizycy; fizycy = Studenci.query( ”exists wykl in this.zapisany_na: wykl.nazwa =\”fizyka\” ”); Z ekstensji Studenci klasy Student wybierany jest podzbiór zgodnie z predykatem będącym argumentem metody query. Ten podzbiór jest podstawiany na zadeklarowany obiekt fizycy. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 12 Java OQL (2) Wiązanie do Java przewiduje specjalną klasę OQLQuery umożliwiającą programiście utworzenie zapytania, przekazanie parametrów do zapytania, wykonanie zapytania oraz przetworzenie jego rezultatu: class OQLQuery{ public OQLQuery(){} public OQLQuery( String query ){ ... } public create( String query ) { ... } public bind( Object parameter ) { ... } public Object execute() throws ODMGException { ... } } Parametry zapytań musza być obiektami w sensie obiektów Java (np. Integer zamiast int). Wynik zapytania powinien być także zadeklarowany jako obiekt. Formalne parametry w zapytaniach są zaznaczone znakiem $i, gdzie i jest numerem parametru. Parametry aktualne są dostarczane poprzez zastosowanie metody bind; i-ty parametr jest ustalany w i-tym wołaniu metody bind. Wołania tej metody powinny poprzedzić wywołanie metody execute, która dokonuje ewaluacji zapytania. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 13 Przykład Java OQL Spośród studentów uczęszczających na przedmiot ”fizyka” należy wybrać Studentów_asystentów, których zarobek jest większy niż 1500, następnie ustalić ich profesorów: Bag fizycy; // Obiekt ulotny do przechowania wybranych studentów Bag profesorowieFizyków; // Obiekt ulotny do przechowania wyniku Double zarobekJakoObiekt; OQLQuery mojeZapytanie; // Deklaracja obiektu do przechowania zapytania fizycy = Studenci.query( ”exists wykl in this.zapisany_na: wykl.nazwa =\”fizyka\” ”); mojeZapytanie = new OQLQuery( ”select a.asystuje_w.prowadzony_przez from Student_asystent as a where a.zarobek > $1 and a in $2” ); zarobekJakoObiekt = new Double(1500.0); mojeZapytanie.bind( zarobekJakoObiekt ); mojeZapytanie.bind( fizycy ); profesorowieFizyków = (Bag) mojeZapytanie.execute(); K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 14 Brak niezgodności impedancji? Patrząc na kod z poprzedniego slajdu, twierdzenie twórców standardu, że unikają oni niezgodności impedancji są niewiarygodne. Rozwiązanie jest nawet bardziej skomplikowane, niż analogiczne rozwiązanie w SQL. W istocie, w tym kodzie mamy deklaracje trzech procedur funkcyjnych (perspektyw, views). Np. takie zadanie mogłoby być zapisane w języku opartym na SBQL/Loqis: procedure fizycy: SetOf Student begin return Student where ”fizyka” in (zapisany_na.Wykład.nazwa); end; procedure profesorStudAsyst( minZarobek: real; moiStudenci: SetOf Student): SetOf Profesor begin return ((Student_asystent)(moiStudenci where zarobek > minZarobek )) . asystuje_w.Wykład.prowadzony_przez.Profesor; end; procedure profesorowieFizyków: SetOf Profesor begin return profesorStudAsyst (1500; fizycy ); end; K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 15 Podsumowanie ODMG 2.0 ma ambicje być de-facto standardem dla obiektowych baz danych. Nie jest pewne, czy nie są to ambicje zbyt wygórowane. • Wiele firm uczestniczy w standardzie i zobowiązało się go podtrzymywać • Model obiektowy ODMG jest rozszerzeniem modelu OMG • Podstawowe funkcjonalności: ODL, OQL • Wiązania do C++ i Smalltalk’a, planowane do Java (niezależnie: Ada) • Związki z OMG i architekturą CORBA Co dalej? W obecnej, już trzeciej wersji standardu, znajduje się wiele rozwiązań kontrowersyjnych i niejednoznaczności. Można mieć wątpliwości, czy taki “standard” ma jakikolwiek sens. Należy mieć nadzieję, że ODMG ugnie się pod cieżarem krytyki i zabierze sie do roboty nad spójną koncepcją, składnią i semantyką. Jeżeli nie, to twierdzenia o “przenaszalności” można będzie włożyć między bajki. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 13, Folia 16