VŠB - Technická univerzita Ostrava Fakulta elektrotechniky a informatiky
DIPLOMOVÁ PRÁCE
2002
Eva Geršiová
VŠB - Technická univerzita Ostrava Fakulta elektrotechniky a informatiky Katedra informatiky
Objektový návrh databázového systému a jeho implementace pomocí objektového rozšíření SQL
2002
Eva Geršiová
Prohlašuji, že jsem tuto diplomovou práci vypracovala samostatně. Uvedla jsem všechny literární prameny a publikace, ze kterých jsem čerpala.
7.5.2002
........................ Eva Geršiová
Děkuji vedoucí diplomové práce Ing. Soně Tiché za odbornou asistenci při jejím vypracovávání.
Abstrakt S rozvojem objektově orientovaných technologií začal tento přístup pronikat i do databází. Již dlouhou dobu užívané relační SŘBD byly obohaceny o nové užitečné prvky objektově orientovaných technologií a vznikly tak objektově-relační SŘBD. Tyto SŘBD umožňují práci se strukturovanými, složitějšími datovými typy. Jsou tedy vhodné zejména pro některé třídy informačních systémů, jako např. systémy pro uložení prostorových dat. Objektově-relační model lze ovšem použít i pro libovolnou jinou třídu informačních systémů.
Klíčová slova objektově-relační SŘBD, informační systém, SŘBD, objektově orientované technologie
Abstract With the development of the object oriented technology this technology has began to leak in the database. For a long time used relation DBMSs were enriched about new useful elements of object oriented technology and the object-relation DBMS were ensued. These DBMSs allowed working with structural, more complex data types. The DBMSs are advisable for any classes of the information systems, for example systems for storage of the spatial data. The object-relation model can be to use for arbitrary class of information system.
Keywords object-relation DBMS, information system, DBMS, object oriented technology
Seznam použitých symbolů a zkratek
API DBMS DFD GIS GUI JDBC ODMG OID OOSŘBD OQL ORSŘBD SQL SŘBD TCP UML XML
-
Application Programming Interface (Aplikační programátorské rozhraní) DataBase Management System Data Flow Diagram (Diagram datových toků) Geographic Information System (Geografický Informační Systém) Graphics User Interface (Grafické uživatelské rozhraní) Java Database Connectivity Object Database Management Group Object Identifier Objektově Orientované Systémy Řízení Báze Dat Object Query Language Objektově Relační Systémy Řízení Báze Dat Structured Query Language Systémy Řízení Báze Dat Transmission Control Protocol Unified Modeling Language eXtensible Markup Language
Přílohy A Uživatelská příručka A.1 Úvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.2 Instalace a spuštění . . . . . . . . . . . . . . . . . . . . A.3 Popis ovládání aplikace . . . . . . . . . . . . . . . . . A.3.1 Popis funkcí systému pro jednotlivé uživatele . A.3.2 Ukázka způsobu práce s informačním systémem B Obsah přiloženého CD
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
68 68 68 69 69 72 76
Kapitola 1
Úvod S rozvojem objektově orientovaných technologií začal tento přístup pronikat i do databázové oblasti informačních technologií. Jelikož ne pro všechny aplikace jsou relační databáze vhodné (např. systémy pro práci s prostorovými daty), začaly se vyvíjet objektově orientované SŘBD – OOSŘBD ([Ben00]). Tyto SŘBD ukládají objekty do databáze a využívají další užitečné vlastnosti objektově orientovaného přístupu. Rozvoj objektově orientovaných SŘBD z různých důvodů nenabyl očekávaných rozměrů. Naopak, začal se prosazovat kompromis mezi objektově orientovanými a relačními ([Sar97]) SŘBD – objektově-relační SŘBD ([StB00]). Objektověrelační přístup využívá robustnosti a vysokého výkonu relační technologie nabyté za dlouhá léta vývoje a některých výhod poskytovaných objektově orientovanými přístupy. Cílem této diplomové práce bylo seznámit se s objektově-relačním modelem v databázích, konkrétně s objektově-relačním modelem SŘBD Oracle ([Ora01]), a prakticky demonstrovat použitelnost objektově-relačního modelu. Praktická použitelnost objektově relačního modelu byla ukázána návrhem a implementací informačního systému katedry, využívajícího tento model. Tento informační systém byl implementován v jazyce Java ([Sun02j], [Von97j], [Ora01ja]). V následujících kapitolách budou popsány použité objektové technologie a implementovaný informační systém. Kapitola 2 se zabývá objektově orientovanými technologiemi včetně objektově-relačních SŘBD, SQL3 a prací s objektově-relačním modelem v programovacím jazyce Java. V kapitole 3 jsou popsány analýza a návrh datové části informačního systému katedry. Kapitola 4 se zabývá analýzou, návrhem a implementací samotné aplikace informačního systému. V závěru (kapitola 5) jsou potom shrnuty nabyté poznatky a zhodnocen přínos objektově-relačních SŘBD s přihlédnutím k praktickému vyzkoušení implementováním informačního systému katedry. Uživatelský manuál aplikace se nachází v kapitole A.
1
Kapitola 2
Objektově orientované technologie a SŘBD Tato kapitola se zabývá objektově-relačními SŘBD a objektovými technologiemi obecně. Kapitola 2.1 pojednává obecně o objektově orientovaných technologiích. Definuje pojmy jako objekt, třída apod. Kapitola 2.2 se zabývá objektově-relačními SŘBD. V této kapitole je rovněž popsán objektově-relační model databáze Oracle a dotazovací jazyk SQL 3. V kapitole 2.3 je popsán způsob práce s objektově-relačním modelem databáze Oracle v programovacím jazyce Java.
2.1
Objektově orientované technologie
V druhé polovině 60. let byl vyvinut programovací jazyk Simula 67, jehož některé rysy jako např. typy, třídy nebo jednoduchá dědičnost se staly základem objektově orientovaných programovacích jazyků. Na počátku 70. let byl vyvinut první čistě objektově orientovaný jazyk Smalltalk. Veškerá jeho data jsou objekty, které si navzájem předávají zprávy. Dalšími jazyky s objektovými rysy jsou C++, Java, C# a další. Oproti strukturovaným programovacím jazykům, kde je program tvořen daty a algoritmy pro práci nad nimi, objektově orientované jazyky pracují na zcela jiných principech. V objektově orientovaných přístupech je realita modelována pomocí objektů a vztahů mezi nimi. Objekt zapouzdřuje data – atributy – a poskytuje vnějšímu světu rozhraní, které je popsáno pomocí metod. Je nutno poznamenat, že některé objektově orientované programovací jazyky (např. C++ nebo Java) umožňují přistupovat k datům přímo, tedy ne výhradně pomocí metod. Množinu objektů se společnými vlastnostmi popisuje třída. Každý objekt je instancí jediné třídy. Lze tedy napsat: Třída = rozhraní + implementace. Příklad 2.1: Mějme třídu OSOBA, která má atributy rodné číslo a jméno. Instancí této třídy (objektem) je např. konkrétní osoba Josef Novák s rodným číslem 700506/5610 nebo Jana Koutná s rodným 2
číslem 805916/4556. Objektově orientovaný přístup je založen na těchto třech principech: • Zapouzdření – data jsou zapouzdřená v objektech a jsou přístupná pouze pomocí metod tvořících rozhraní. • Dědičnost – třída může dědit vlastnosti (atributy) nebo chování (metody) svých předků. Zděděné metody mohou být předefinovány. Třída, která se nazývá podtřída, je dědicem třídy zvané nadtřída (super třída). Podle, toho zda třída může dědit z jedné nebo více tříd, rozlišujeme programovací jazyky s jednoduchou nebo násobnou dědičností. • Mnohotvárnost – umožňuje společné pojmenování vlastností (metod) v hierarchii tříd se specifickou implementací pro kteroukoliv třídu. Objekt je identifikovatelná individuální entita, která má • identitu – objekt je jedinečný – jednoznačně odlišitelný od ostatních objektů, • chování – služby, které poskytuje v interakci s ostatními objekty. Sekundárními znaky objektů jsou: • atributy – v čase proměnné, • životní cyklus – od vytvoření po jeho destrukci, • stavy – odráží různé fáze v životním cyklu objektu. Atributy lze rozdělit do dvou skupin: • členské atributy – atributy, jejichž hodnota tvoří stav objektu a • statické (třídní) atributy – atributy, jež jsou sdíleny všemi objekty dané třídy. Rovněž metody je možné rozdělit do dvou skupin: • členské – metody, které se volají na instanci třídy (tedy objekt) a • statické (třídní) – statické metody je možno volat na třídu (tedy bez vytvoření instance třídy), tyto metody nemohou manipulovat s členskými atributy a volat členské metody. Více o objektově orientovaných přístupech je možno nalézt např. v [Von97].
3
Příklad 2.2:
class Car { String type; public Car(String type) { this.type = type; } public void stop {...} public void start {...} } public static void main(String[] args) { Car fiat = new Car("Fiat"); fiat.start(); Car skoda = new Car("Skoda"); skoda.start(); } V příkladu 2.2 vidíme ukázku třídy Car v programovacím jazyce Java s jediným atributem type typu String. Rozhraní této třídy je tvořeno dvěma metodami. Metodou start(), která rozjede auto a metodou stop(), která zastaví auto. Ve statické metodě main jsou vytvořeny dvě instance této třídy fiat a skoda. Na obě auta je zaslána (zavolána) metoda start(). Příklad 2.3:
class Truck extends Car { float capacity; public Truck(String type, float capacity) { super(type); this.capacity = capacity; } public float getCapacity() { return capacity; } public void start() { ... } } V příkladu 2.3 je uvedena třída Truck, která dědí ze třídy Car. Tato třída tedy obsahuje atribut type a nově atribut capacity, metody stop(), start() a nově metodu getCapacity(). Tyto metody tvoří rozhraní této třídy. Zde vidíme jeden ze základních rysů objektově orientovaného přístupu a tou je znovupoužitelnost kódu. Všimněme si mnohotvárnosti – metoda start() je ve třídě Truck předefinována. Třída zapouzdřuje data (type a 4
capacity) a poskytuje metody pro operace nad nimi (např. getCapacity() vrátí kapacitu přiřazenou objektu). S rozvojem objektově orientovaných technologií rostla i potřeba vytvoření metod pro modelování vývoje systémů napsaných v objektově orientovaných programovacích jazycích. Vyvinula se jich celá řada. Např. OMT, OOSE, UML a další. UML je v současnosti nejobsáhlejším jazykem s notací pro specifikaci, konstrukci, vizualizaci a dokumentaci modelů pro vývoj softwaru. Více o objektově orientovaných metodách je možno nalézt např. v [Von95] nebo [Von97]. V následující kapitole bude popsáno, jakým způsobem pronikaly objektově orientované technologie do technologií databázových.
2.2
Objektově-relační SŘBD
S rozvojem objektově orientovaných technologií začal tento trend pronikat i do oblasti databází. Ovšem některé rysy objektově orientovaných přístupů se v databázích objevily již dříve. Např. v síťovém datovém modelu (1971) je každému záznamu přiřazen jedinečný identifikátor (databázový klíč ). Pro některé aplikace se ukazuje nevhodné použít relační model, proto se začaly vyvíjet objektově orientované SŘBD (OOSŘBD). Tyto SŘBD ukládají do databáze objekty a využívají další užitečné vlastnosti objektově orientovaného přístupu. V 90. letech existovalo několik prototypů či komerčních OOSŘBD. Očekávalo se, že tento nový trend razantně nahradí klasické relační SŘBD. V roce 1997 vydala organizace ODMG specifikaci ODMG 2.0, což je de-facto standard pro objektové databáze. V roce 2000 byla vydána specifikace ODMG 3.0 ([ODMG00]). Velké množství aplikací využívajících relační technologii není nutné přepisovat do technologie jiné. Rovněž pro většinu nově vznikajících aplikací byla relační technologie dostačující. Relační model se také za svou dlouhou dobu existence značně zdokonalil. Brzy se tak ukázalo, že počet nasazení OOSŘBD neroste tak rychle, jak se předpokládalo. Také funkce těchto systémů jsou dnes na poměrně nízké úrovni. Z praxe se ukázalo, že vhodným kompromisem je objektově-relační SŘBD (ORSŘBD). Za jeho zakladatele se považuje Won Kim. Cílem objektově-relačního modelu je vytěžit maximum z rozsáhlých investic do relační technologie a zároveň využít výhod objektového modelu. Objektově relační přístup tak využívá robustnosti a vysokého výkonu relační technologie nabyté za dlouhá léta vývoje a některých výhod poskytovaných objektově orientovanými přístupy. Více o ORSŘBD je možno nalézt v [StB00]. Ukázalo se, že objektově-relační SŘBD je ideálním rozšířením relačních SŘBD, jelikož do relačních databází se dodávají nové prvky, které zdokonalují původní systém. Pro nové firmy, které teprve začaly své systémy budovat, byla volba jednoduchá. Začaly psát nový objektověrelační systém od základů. Ovšem spousta firem (Informix, IBM, Oracle a další) již systémy vybudované měly a to samozřejmě SŘBD relační. Pro tyto firmy nastal problém, jakým způsobem začlenit objektový přístup do svých systémů, popřípadě zda nevytvořit systém zcela nový. Vytvoření zcela nového systému by bylo ovšem velmi nákladné nejen finančně, ale také časově. Proto některé firmy zvolily metodu postupného vývoje (např. firma Oracle), která spočívá v tom, že svůj relační databázový server postupně obohacují o nové prvky (např. 5
složité a strukturované datové typy, uživatelsky definované funkce apod.). Dnes je, paradoxně, objektově-relační model brán jako vylepšení modelu relačního ([Pok00]). Objektové či objektově-relační SŘBD se zejména využívají tam, kde jsou klasické nestrukturované datové typy relačního modelu nedostatečné. Např. systémy pro uložení prostorových dat (CAD, GIS a další). Další výhodou objektově-relačních SŘBD je možnost ukládání multimediální dat (zvuků, obrázků nebo animací) a velkých binárních nebo textových dat obecně. Podstatnou změnou je to, že záznam (instance objektového typu) je v databázi jednoznačně identifikovatelný pomocí reference, tzn. pro záznamy není nutné definovat primární klíče, jako je tomu u relačního modelu. V kapitole 2.2.1 bude stručně popsán objektově-relační model SŘBD Oracle a zároveň budou na tomto SŘBD demonstrovány některé rysy objektově-relačních SŘBD obecně. Existují dvě větve vývoje dotazovacích jazyků s objektovými prvky. Prvním je OQL (Object Query Language – objektový dotazovací jazyk) popsaný v ODMG 3.0 ([ODMG00]). Tento jazyk byl vytvořen jako čistě objektový a s vývojem se do něj zařadily některé relační prvky. Jako druhý se v roce 1992 začal vyvíjet dotazovací jazyk pracující s objektově-relačním modelem, který byl nazván SQL3 ([SQL3],[YCH99]). Tento jazyk vznikl zařazením objektových prvků do SQL92. Jazyk SQL3 je stručně popsán v kapitole 2.2.2.
2.2.1
Objektově-relační model SŘBD Oracle
Pro objektově orientované modelování je charakteristická především bohatost datových typů, které jsou k dispozici a pomocí nichž lze snadno modelovat a implementovat vlastní objektové typy. Příkladem může být uložení záznamu pro nějaký státní útvar v informačním systému pro práci s geografickými daty (GIS). V objektově-relační databázi je možné prostorový tvar státu uložit jako hodnotu jediného atributu objektového (strukturovaného) typu, i když se tento tvar může skládat ze stovek prostorových bodů. Oracle je SŘBD, který je postupně doplňován o objektová vylepšení do již vytvořené relační databáze. Objektově-relační model SŘBD Oracle 9i je popsán v [Ora01o]. Je skutečností, že nadstavba SQL umožňující práci s objektovými rysy objektově-relačního modelu SŘBD Oracle není kompatibilní s SQL3. Oracle implementuje objekty jako instance uživatelem definovaných datových typů. V současnosti jsou podporovány tyto typy: • objektový typ a • kolekce, které dále dělíme na – pole proměnné délky, – vnořená tabulka. Datové typy jsou šablony (třídy), jejichž instance (objekty) se vkládají do tabulek objektových datových typů. Dále budou popsány jednotlivé definované datové typy.
6
2.2.1.1
Objektový typ
Objektový typ je uživatelsky definovaný složený datový typ, který zapouzdřuje data spolu s metodami potřebnými k manipulaci s daty. Od verze 9i je v Oracle možná dědičnost. Ovšem pouze dědičnost jednoduchá, což znamená, že třída může dědit pouze z jedné nadtřídy. Každý objektový typ má metodu zvanou konstruktor, která je implicitně vygenerována systémem. Jméno vytvořeného konstruktoru je shodné se jménem objektového typu, pro který je definován. Při vytvoření objektového typu se nealokuje žádné paměťové místo. To se vytvoří pouze při inicializaci instance objektového typu pomocí konstruktoru. Objektový typ reprezentuje entitu reálného světa, jako např. student, bankovní účet apod. Objektový typ má tyto charakteristické vlastnosti: • Jedinečné jméno. • Atributy – proměnné, které tvoří strukturu dat. Atributy objektu mohou být těchto typů: – primitivní datový typ (VARCHAR2, NUMBER, . . . ), – jiný objektový typ – umožňuje vytvářet neatomické atributy, – kolekce (pole proměnné délky nebo vnořené tabulky) – taktéž umožňuje vytvářet neatomické atributy, – typy pro uložení velkých nestrukturovaných dat (CLOB, BLOB, . . .). • Metody – funkce a procedury charakterizující chování objektového typu. Metody se definují jako část objektového typu, jsou implementovány pomocí PL/SQL ([Ora01p]) a uloženy v databázi. Metody je možné rovněž psát pomocí programovacích jazyků C nebo Java. Metody dělíme na: – Funkce nebo procedury – tyto metody mohou mít parametry. Rozdíl mezi funkcí a procedurou je v tom, že funkce vždy vrací hodnotu zatímco procedura ne. – Metody porovnávací – tyto metody jsou definovány pro účely porovnání objektů. Rozlišujeme dva typy těchto metod: ∗ Funkce MAP - definuje se pomocí klíčového slova MAP. Kdykoliv je potřeba porovnat dva objekty, Oracle implicitně volá tuto metodu (pokud je definována). Dvě instance je poté možno porovnávat dle uživatelem určené hodnoty (například podle hodnoty nějakého atributu). ∗ Funkce ORDER - definuje se pomocí klíčového slova ORDER. Tuto metodu lze také použít pro porovnání dvou objektů. Vstupním parametrem této metody je instance stejného datového typu. V případě, že se instance shodují, vrací metoda hodnotu 0. V opačném případě vrátí hodnotu -1 nebo 1 (tedy výsledek porovnání těchto dvou instancí). V objektově-relačním modelu je ke všem atributům veřejný přístup, tzn. jejich hodnoty lze získávat a nastavovat bez použití metod. Metody tedy spíše provádějí nějaké složitější 7
operace nad daty. V SQL3 (kapitola 2.2.2) jsou pro všechny atributy automaticky generovány metody pro získání a nastavení hodnot atributů. Tyto metody nejsou u objektově-relačního modelu SŘBD Oracle generovány. Příklad 2.4: Máme za úkol vytvořit objektový typ TPerson s atributy, ve kterých budou uloženy jednotlivé informace o osobě v informačním systému. CREATE OR REPLACE TYPE TPerson AS OBJECT ( login VARCHAR2(6), fname VARCHAR2(20), sname VARCHAR2(20), address TAddress, birth DATE, tel1 NUMBER(20), tel2 NUMBER(20), www CLOB, email CLOB, passwd VARCHAR2(10) ) NOT FINAL NOT INSTANTIABLE; CREATE OR REPLACE TYPE TAddress AS OBJECT ( street VARCHAR2(30), city VARCHAR2(30), PSC NUMBER(5) ); Vidíme, že některé atributy jsou klasických datových typů (např. login) a jiné objektových typů, jako např. address je typu TAddress – tento atribut je tedy neatomický. Klíčovým slovem NOT FINAL určujeme, že z této třídy bude možné dědit, NOT INSTANTIABLE pak říká, že není možné vytvořit instanci této třídy. Taková třída se nazývá abstraktní. Tato třída bude sloužit jako nadtřída pro jiné třídy. Příklad 2.5: Nyní máme za úkol vytvořit typ TStudent, který bude dědit ze třídy TPerson z předchozího příkladu. CREATE OR REPLACE TYPE TStudent UNDER TPerson ( grup REF TGroup, year NUMBER(2), specc REF TSpec, branch REF TBranch, STATIC FUNCTION authentication (login VARCHAR2, password VARCHAR2, md NUMBER) RETURN REF TStudent ); 8
Objektový typ TStudent tedy dědí z objektového typu TPerson (všimněme si klíčového slova UNDER), což znamená, že TStudent obsahuje všechny atributy typu TPerson, navíc další atributy a metodu deklarovanou v typu TStudent. Všimněme si, že metoda authentication je statická, což znamená, že je volána na třídu a ne na instanci třídy. Dále si všimněme například atributu grup. Tento atribut je datového typu REF, jedná se tedy o referenci na instanci typu TGroup uloženou v nějaké tabulce objektového typu TGroup. Oracle povoluje i neúplné objektové typy. Ty se využívají v případě, že při vytváření objektových typů nejsou k dispozici všechny informace pro vytvářený objektový typ, ale jiný objektový typ je závislý na jeho existenci dříve, než tento typ může být vytvořen. Neúplné objektové typy pouze specifikují jméno objektového typu. Atributy a metody specifikovány nejsou. Syntaxe pro vytvoření neúplného objektového typu je následující: CREATE TYPE type_name;
2.2.1.2
Kolekce
Kolekce jsou objekty, které lze použít pro efektivní uložení více výskytů prvků stejného datového typu. Kolekce je tedy homogenní pole proměnné délky, které lze použít jako atribut objektového typu. Pole umožňuje uložení více instancí datového typu ve sloupci – je to tedy další způsob vytvoření neatomického atributu. Kolekce lze rozdělit na: • Pole proměnné délky (VARRAY) – seřazené pole uložené ve sloupci tabulky, složené z omezeného počtu instancí stejného typu. Seřazení v tomto případě znamená, že prvky jsou v poli umístěny na danou pozici (což je rozdíl oproti vnořeným tabulkám). Název pole proměnné délky je poněkud zavádějící, protože pole má danou maximální kapacitu. • Vnořené tabulky – obsahují neomezený počet neseřazených datových prvků stejného typu (instance tedy nejsou vkládány na určitou pozici ve vnořené tabulce). Vnořené tabulky mohou obsahovat pouze jeden atribut, jehož datový typ může být: – interní datový typ nebo – uživatelem definovaný objektový typ. Vnořená tabulka (na rozdíl od pole proměnné délky) má opravdu proměnnou délku a lze ji použít například jako: – datový typ sloupce, – atribut objektového typu, – proměnnou v PL/SQL. Vnořenou tabulku si můžeme představit jako tabulku, která je uložena jako hodnota atributu jiné tabulky. V tomto případě ovšem pracujeme s objektovými tabulkami, typy a instancemi těchto typů. Otázkou je, kdy je vhodnější použít pole proměnné délky a kdy vnořenou tabulku. Vnořenou tabulku je výhodnější použít v těchto případech: • Pokud nezáleží na pořadí instance typu v kolekci. 9
• Je-li požadováno indexování atributu typu vnořené tabulky. • Pokud není znám maximální počet prvků kolekce. • Pokud je nutné provádět dotazy nad instancí typu vnořené tabulky.
Pole proměnné délky resp. vloženou tabulku lze vytvořit následujícím způsobem: CREATE TYPE type_name AS [VARRAY | VARYING ARRAY] (number_of_elements_in_type) OF datatype CREATE TYPE type_name AS TABLE OF datatype; Příklad 2.6: Vezměme například přihlašování se studentů na termíny úkolů v informačním systému katedry. Pro každý úkol je možné vypsat několik termínů, na které se mohou studenti hlásit. Nejprve vytvoříme typy pro úkol (TTask) a termín (TTerm). Vnořené tabulky mohou obsahovat pouze jeden atribut, což je v případě TStudentRef splněno a není tak nutné vytvářet další typ. Tabulka objektového typu TStudents nt je poté umístěna jako atribut people typu termínu (TTerm). CREATE OR REPLACE TYPE TStudentRef AS OBJECT ( student REF TStudent ); CREATE OR REPLACE TYPE TStudents_nt AS TABLE OF TExam; CREATE OR REPLACE TYPE TTerm AS OBJECT ( task REF TTask, assign REF TTeacher, beg DATE, deadline DATE, num NUMBER(3), room REF TRoom, capacity NUMBER(3), num_example NUMBER(2), note CLOB, people TStudents_nt ); Při vytváření objektové tabulky je nutné explicitně zadat název vnořené tabulky. CREATE TABLE Term_table OF TTerm NESTED TABLE people STORE AS People_table; 10
V relačním modelu bychom nejspíš vazbu mezi termínem a studentem museli realizovat pomocí vazební tabulky, jelikož se jedná o vazbu M:N (v objektově-relačním modelu můžeme samozřejmě tuto vazbu realizovat stejným způsobem). Výše popsaný způsob tak v podstatě vkládá tuto vazební tabulku do tabulky jiné. Vkládání do vnořené tabulky je samozřejmě komplikovanější. První vnořený dotaz musí vybrat danou vnořenou tabulku. Sekce VALUES nebo druhý vnořený dotaz musí obsahovat sloupce, které se musí shodovat se sloupci jedné z vnořených tabulek. Příklad 2.7: Následujícím příkazem vložíme referenci na instanci TStudent z tabulky Student table s hodnotou ger024 atributu login do vnořené tabulky uložené v atributu people tabulky Term table z řádků s hodnotou 15 atributu capacity. Jinak řečeno student se studentským číslem ger024 bude zapsán na všechny termíny s kapacitou 15. INSERT INTO THE (SELECT t.people FROM Term_table t where t.capacity = 15) SELECT REF(s) FROM Student_table s WHERE s.login = ’ger024’; Tento příklad není tak úplně smysluplný, ale dobře demonstruje vkládání do vnořené tabulky. V případě, že budeme chtít vkládat přímo námi dané hodnoty (a ne hodnoty získané pomocí SELECT jako v tomto případě), pak musíme použít sekci VALUES. Příklad 2.8: V tomto příkladu jsou vymazány všechny záznamy ze všech vnořených tabulek, které jsou uloženy v atributu people tabulky Term table a které obsahují referenci na studenta (v atributu student) s hodnotou ger024 atributu login (tedy referenci na instanci TStudent z tabulky Student table). Tímto příkazem jsou tedy zrušeny všechny přihlášky na termíny úkolů pro studenta se studentským číslem ger024. DELETE TABLE (SELECT t.people FROM Term_table t) e WHERE e.student IN (SELECT REF(s) from Student_table s WHERE s.login = ’ger024’); Příklad 2.9: V tomto příkladu chceme vypsat studentská čísla všech studentů, kteří jsou přihlášeni na nějaký termín. SELECT s.login FROM Student_table s, Term_table t1, TABLE(t1.people) t2 WHERE t2.student = REF(s);
2.2.1.3
Typ reference
V objektově-relačním modelu můžeme definovat atribut typu reference na instanci objektového typu, která je uložena jako jeden řádek v objektové tabulce. Reference (objektová reference, OID – jedinečné číslo objektu) jednoznačně identifikuje instanci v databázi. Zavedením 11
reference není již nutné v objektově-relačním modelu používat primární klíče. Reference je v SŘBD Oracle reprezentována datovým typem a funkcí REF. Rozlišují se dva typy referencí: • REF bez rozsahu (Unscoped REF ) – REF bez rozsahu není vázána na konkrétní tabulku – je deklarována jako reference na objektový typ. Nevýhodou je, že tato reference musí obsahovat informace o objektových tabulkách, na které se reference odkazuje a zabírá tak poměrně hodně místa. Deklarace REF bez rozsahu: attribute_name REF Object_type_name;. V příkladu 2.5 je např. atribut grup typu TStudent referencí na instanci TGroup. • REF s rozsahem (Scoped REF ) – REF s rozsahem je reference na instanci objektového typu vázanou pouze na jednu objektovou tabulku (reference musí být samozřejmě deklarována jako reference na stejný typ jako typ objektové tabulky). Takovéto omezení nám při datovém modelování nemusí v některých případech prakticky vadit a za toto omezení dostáváme referenci zabírající méně místa než REF bez rozsahu a rovněž rychlejší přístup k datům. REF s rozsahem se deklaruje až u objektových tabulek. Deklarace REF s rozsahem: SCOPE FROM (attribute_name) IS Object_table_name; Reference, která se neodkazuje na žádnou instanci, se nazývá dangling. Oracle SQL poskytuje operátor IS DANGLING, který umožňuje otestovat nějakou referenci, zda se odkazuje či neodkazuje na nějakou existující instanci. Jestliže chceme provést dereferenci nějaké reference (tedy získání hodnoty instance dané referencí), můžeme použít operátor DEREF. Můžeme použít i implicitní dereferenci. Příklad 2.10: Mějme nějakou instanci typu TStudent z objektové tabulky Student table (viz příklad 2.5). Jméno skupiny tohoto studenta lze získat pomocí implicitního dereferencování takto: s.grup.name. Dereferencování reference, která se neodkazuje na žádnou existující instanci (tzv. dangling reference), vrací null objekt. Pokud chceme získat referenci na nějakou instanci, pak použijeme funkci REF(). Příklad 2.11: V tomto příkladu vidíme použití funkce REF(). Referenci na instanci TStudent z tabulky Student table s hodnotou ger024 atributu login lze získat tímto příkazem. SELECT REF(s) FROM Student_table s WHERE s.login = ’ger024’; Jak již bylo řečeno, tak po zavedení objektových referencí není nutné v objektově-relačním modelu používat primární klíče. Pomocí cizích klíčů (primárních klíčů jiných tabulek) bylo v relačním modelu realizováno spojení dvou tabulek. Příklad 2.12 ukazuje spojení realizované pomocí objektových referencí.
12
Příklad 2.12: V informačním systému chceme vypsat jméno diplomové práce (hodnotu atributu name z tabulky Thesis table), kterou má zapsanou student s jedinečným osobním číslem ger024. Diplomová práce je abstrahována typem TThesis. CREATE OR REPLACE TYPE TThesis AS OBJECT ( student REF TStudent, head REF TTeacher, name VARCHAR2(100), typ NUMBER(1), year_assig NUMBER(4), text_assig CLOB, year_defence NUMBER(4), opponent REF TTeacher, head_eval CLOB, opp_eval CLOB, abstract CLOB, keyword CLOB ); Chceme tedy provést přirozené spojení tabulek Thesis table a Student table přes objektovou referenci v atributu student. SELECT t.name from Student_table s, Thesis_table t WHERE (s.login = ’ger024’) AND (t.student = REF(s)); Příklad 2.13: Pokud chceme vypsat atributy všech objektů z tabulky Student table, můžeme použít klasický SQL SELECT: SELECT * FROM Student_table;. Také můžeme pomocí SELECT REF(s) FROM Student_table s; získat objektové reference a poté získat hodnoty jednotlivých atributů dereferencováním těchto referencí.
2.2.1.4
Objektové tabulky
V objektově-relačním modelu lze vytvářet tzv. objektové tabulky, což jsou tabulky, které si lze představit jako klasické tabulky obsahující v řádcích objekty (instance typu) a ve sloupcích hodnoty atributů typu. Objektová tabulka se vytváří následujícím způsobem: CREATE TABLE table_name OF type_name; kde type name je typ, jehož instance jsou uloženy v tabulce. Objektová tabulka je tedy v podstatě homogenní pole proměnné velikosti. V objektově-relačním modelu je možné využít všech výhod poskytovaných relačním modelem, jako je definování indexovaných atributů 13
(tedy sloupců objektové tabulky), zadání integritních omezení atributů atd. Jestliže se na množinu instancí (objektovou tabulku) díváme jako na tabulku, můžeme využívat klasických SQL příkazů jako je SELECT, INSERT, UPDATE a DELETE. Příklad 2.14: V informačním systému katedry chceme evidovat skupiny studentů. Pro evidenci skupin vytvoříme typ TGroup a objektovou tabulku Group table. CREATE OR REPLACE TYPE TGroup AS OBJECT ( name VARCHAR2(4) ); CREATE TABLE Group_table OF TGroup; Každému řádku (tedy objektu), který je v databázi vytvořen, je přidělen globální, jednoznačný a nezaměnitelný identifikátor – tzv. OID (Object Identifier ). Systém Oracle ukládá generované OID do skrytého sloupec, který je indexován. Skutečnost, že tento sloupec je skrytý, je velký rozdíl oproti SQL3, kde neexistuje funkce REF() a kde je reference uložena v jednom sloupci objektové tabulky. Tento identifikátor umožňuje objektovým typům odvolávat se na řádky v objektové tabulce. Toto odkazování je realizováno pomocí struktury REF. Objektová tabulka ve skutečnosti neukládá data interně, avšak obsahuje reference, nebo se odkazuje na externí tabulku, která obsahuje data jednotlivých řádků. V SŘBD Oracle je možné definovat tabulku jako typ atributu. Takové tabulce pak říkáme vnořená tabulka (viz příklad 2.6).
2.2.1.4.1 Integritní omezení Na atributy objektového typu nelze zadávat integritní omezení. Integritní omezení lze nadefinovat na objektové tabulky stejným způsobem jako na tabulky relační. Na tomto rysu vidíme podstatnou vlastnost objektově-relačního modelu: využívá rysy objektových (např. objektové typy) a zároveň relačních technologií (např. integritní omezení). Příklad 2.15: V informačním systému katedry budeme chtít, aby evidované místnosti měly vždy zadané jméno a typ místnosti (zda jde o učebnu nebo kabinet). Navíc požadujeme, aby název místnosti byl unikátní. Místnost je reprezentována typem TRoom. CREATE OR REPLACE TYPE TRoom AS OBJECT ( name VARCHAR2(5), capacity NUMBER(3), phone NUMBER(4), shoolroom CHAR(1) ); Integritní omezení jsou v objektově-relačním modelu definovány při vytváření objektových tabulek. V tomto případě při vytváření objektové tabulky Room table typu TRoom. 14
CREATE TABLE Room_table OF TRoom (CONSTRAINT IO_ROOM_1 name UNIQUE NOT NULL, CONSTRAINT IO_ROOM_2 shoolroom NOT NULL); V objektově-relačním modelu jsou primární klíče známé z relačního modelu nahrazeny objektovými referencemi. Je nutné na atribut, který je referencí na instanci objektového typu (tedy jakýmsi cizím klíčem), definovat takové integritní omezení, aby nebylo možné smazat záznam, na který se odkazuje nějaká hodnota (reference) tohoto atributu. Příklad 2.16: V tomto příkladu chceme nastavit takové integritní omezení atributu department (je deklarován jako department REF TDepartment, neboli je to reference na instanci TDepartment), aby nebylo možné smazat instanci TDepartment, na kterou se odkazuje nějaká hodnota atributu department záznamu tabulky Department table. V následující ukázce vidíme, kromě nastavení integritních omezení dalších atributů, i nastavení takového integritního omezení pomocí klíčového slova REFERENCES. U tohoto atributu není rovněž možná prázdná hodnota (NULL). CREATE TABLE Teacher_table OF TTeacher (CONSTRAINT IO_TEACHER_1 login UNIQUE NOT NULL, ... CONSTRAINT IO_TEACHER_7 department NOT NULL REFERENCES Department_table, CONSTRAINT IO_TEACHER_8 enlistment NOT NULL );
2.2.1.5
Programovací jazyk metod - PL/SQL
Metody objektových typů lze psát buď v programovacích jazycích jako C nebo Java, nebo přímo v PL/SQL ([Ora01p]). Jazyk PL/SQL obsahuje procedurální rozšíření jazyka SQL. Syntaxe jazyka PL/SQL vychází z programovacího jazyku Ada. PL/SQL se používá ve všech produktech systému Oracle. Obecně je PL/SQL blokově strukturovaný jazyk. Jeho základní jednotky - procedury, funkce a anonymní bloky jsou logické bloky, které mohou obsahovat další vložené bloky. Blok PL/SQL je definován:
DECLARE -- deklarace BEGIN -- tělo EXCEPTION -- ošetření výjimek END; 15
PL/SQL blok se tedy skládá ze tří částí: • deklarace - obsahuje definici proměnných a kurzorů, • tělo - spustitelný kód, tento kód lze rozdělit do podbloků, • ošetření výjimek. Příklad 2.17: V informačním systému katedry je nutné, aby se každý uživatel autentizoval (tedy aby zadal své číslo a heslo pro svou identifikaci). Pro identifikaci studenta slouží statická metoda authentication() typu TStudent. Metoda se deklaruje při definici typu. CREATE OR REPLACE TYPE TStudent UNDER TPerson ( grup REF TGroup, year NUMBER(2), specc REF TSpec, branch REF TBranch, STATIC FUNCTION authentication (login VARCHAR2, password VARCHAR2) RETURN REF TStudent ); Metodu můžeme definovat později. CREATE OR REPLACE TYPE BODY TStudent AS STATIC FUNCTION authentication (login VARCHAR2, password VARCHAR2) RETURN REF TStudent IS studentRef REF TStudent; BEGIN SELECT REF(s) INTO studentRef FROM Student_table s WHERE (s.login like login) AND (s.passwd like password); RETURN studentRef; END authentication; END; Vidíme, že v PL/SQL můžeme zacházet s objektovou referencí jako s klasickou proměnnou (např. proměnná studentRef), kterou lze naplnit příkazem SELECT. Příklad 2.18: V tomto příkladu opět vidíme způsob práce s objektovou referencí. Pokud například výsledek předchozího dotazu (referenci) uložíme v PL/SQL bloku do proměnné sref, která je deklarována jako sref REF TStudent, pak můžeme napsat následující dotaz v témže PL/SQL bloku. SELECT login FROM student_table s WHERE Ref(s) = sref; 16
2.2.1.6
Volání metod
V objektově-relačním modelu můžeme definovat metody objektových typů. Na začátku této kapitoly jsme metody rozdělily na členské a statické. Členská metoda je metoda, která může být volána pouze na instanci objektového typu. Příklad 2.19: Jestliže by typ TTeacher obsahoval členskou metodu getSName(), která by vracela příjmení učitele s jedinečným osobním číslem ben64, můžeme použít následující příkaz: SELECT t.getSName() from Teacher_table t WHERE t.login=’ben64’; Tento příklad není úplně smysluplný (protože příjmení je možné získat projekcí atributu sname na objektovou tabulku Teacher table), ale dobře ukazuje způsob volání členských metod. Statická metoda může být volána na typ bez vytvoření instance tohoto typu. Příklad 2.20: Typ TStudent obsahuje statickou metodu authentication() sloužící pro identifikaci studenta. Následujícím příkazem bude tato metoda zavolána s parametry ger024 (jedinečné osobní číslo) a bbb (heslo). Statická je tato metoda proto, že nepracuje s konkrétní instancí TStudent, ale prohledává celou objektovou tabulku Student table a zjišťuje, zda student s jedinečným číslem ger024 má heslo bbb. SELECT TStudent.authentication(’ger024’,’bbb’) FROM Student_table s;
2.2.2
SQL3
V této kapitole bude ve stručnosti popsán v současné době vyvíjený standard databázového jazyka SQL3 ([SQL3], [YCH99]). Dotazovací jazyk SQL3 je vyvíjen organizacemi ANSI a ISO a je zdola kompatibilní s jazykem SQL-92. Je skutečností, že dotazovací jazyk objektověrelačního SŘBD Oracle není kompatibilní s tímto standardem. SQL3 je vyvíjen pro podporu objektově-relačních SŘBD a zavádí tyto struktury: 1. uživatelsky definované typy (UDT); 2. konstruktory a reference objektů; 3. různé typy kolekcí; 4. uživatelsky definované funkce a procedury; 5. podpora pro velké datové typy (znakové – CLOB a binární – BLOB).
17
Uživatelsky definovaný typ (UDT) zapouzdřuje atributy a operace do jedné entity. UDT je specifikován množinou deklarací atributů, které představují stav UDT, operací, které umožňují porovnávat a třídit instance typů, a operací, které definují chování UDT. SQL3 podporuje dědičnost typů, která se definuje klíčovým slovem UNDER. Je podporována pouze jednoduchá dědičnost. Příklad 2.21: Následujícími příkazy vytvoříme typ employee t a tabulku Employee table s atributem employee, který je instancí typu employee t. CREATE TYPE employee_t ( name CHAR(20), address address_t, manager employee_t, hiredate DATE, base_salary DECIMAL(7,2), NOT FINAL METHOD working_years() RETURNS INTEGER <metoda může být definována později příkazem CREATE METHOD> ); CREATE TABLE Employee_table { employee employee_t, serial_number INTEGER }; Pro každý atribut je automaticky vytvořena metoda pro jeho získání a nastavení. Z následující ukázky vidíme, jakým způsobem lze vypsat hodnoty některých atributů pro zaměstnance se sériovým číslem > 1000. SELECT employee.name(), employee.manager.name() FROM Employee_table WHERE serial_number > 1000; SQL3 umožňuje definovat metody EQUAL a LESS pro porovnání instancí typů a funkce HASH a RELATIVE pro řízení třídění instancí typů. Pro konverzi typu na jiný je možné definovat funkce CAST.
2.2.2.1
Tabulky typů
V SQL3 je možné vytvořit tzv. tabulku typů, tzn. tabulku, v jejichž řádcích jsou uloženy instance typu. Obecná syntaxe i příklad je následující:
18
CREATE TABLE
OF REF IS CREATE TABLE T OF employee_t REF IS reference_column; V každé takové tabulce je vytvořen sloupec (např. reference column z předchozího příkladu), který obsahuje referenci, která jednoznačně identifikuje řádek (tedy instanci typu). V SQL3 je možné dědit i z tabulek typů. Podmínkou je, aby tabulka dědící z jiné tabulky byla tabulkou typu, který je podtypem typu nadtabulky.
2.2.2.2
Reference
Dalším uživatelsky definovaným typem je typ reference (REF). Hodnota typu reference definovaná pro UDT je jedinečná hodnota, která identifikuje specifickou instanci typu. Hodnota typu reference může být uložena v tabulce jako reference na řádek jiné tabulky, nebo může být uložena v hodnotě atributu jiného typu a poskytovat tak tomuto objektu referenci na objekt jiný. Příklad 2.22: Chceme vytvořit typ Account jehož atribut empl je referencí na instanci typu employee t. CREATE TABLE Account ( acctno INT, empl REF(employee_t), type CHAR(1), opened DATE ); Hodnota atributu empl je referencí na instanci typu employee t (tedy na řádek tabulky tohoto typu). Jestliže je v definici tabulky použito klíčové slovo SCOPE, pak jsou reference omezeny pouze na řádky jedné objektové tabulky. Příklad 2.23: V tomto příkladu vidíme způsob práce s referencemi a především jejich dereferencování. SELECT a.empl->name() FROM Account a WHERE a.empl->address.city()="Hollywood" AND a.acctno > 100000;
2.2.2.3
Kolekce
V SQL3 je možné použít kolekci jako pole pro uložení instancí datových typů. Pole má proměnnou velikost s definovanou maximální velikostí, přičemž nelze vytvořit pole polí. Příklad 2.24: V tomto příkladu vidíme jakým způsobem lze vytvořit tabulku s atributem typu pole a vkládání do takové tabulky. 19
Java ([Sun02j],[Von97j],[CGI97]) je objektově orientovaný programovací jazyk vyvinutý firmou Sun Microsystems. Jeho výhodou je bezpochyby možnost psát aplikace přenositelné na všechny v současné době existující platformy bez nutnosti kompilace. Nevýhodou je naopak značná náročnost na hardwarové vybavení počítače a neexistence normy vydané některou z mezinárodních institucí. Pro práci se SŘBD je Java vybavena Java Database Connectivity – JDBC ([Sun02d]), což je aplikační programátorské rozhraní (API) pro práci se SŘBD. JDBC poskytuje řadu rozhraní, jejichž implementaci poskytují jednotliví výrobci. Výhodou je tedy stejná práce se SŘBD různých výrobců. Tato výhoda samozřejmě platí pouze v případě použití modelu popsaného nějakou normou (např. SQL92). JDBC je natolik silným nástrojem, že pomocí něj lze např. bezproblémově volat PL/SQL funkce z klientských Java aplikací nebo pracovat s objektovými typy databáze Oracle. JDBC se používá k vytváření dynamických SQL dotazů (tedy dotazů, které lze měnit za chodu aplikace). Pro SQL dotazy, které jsou známy v čase kompilace programu, lze použít SQLJ ([Ora01]). Podpora programovacího jazyka Java je v SŘBD Oracle zavedena od verze 8i. V programovacích jazycích jako je C nebo Java lze psát nejen klientské aplikace, ale vytvořené funkce resp. metody lze vkládat do vlastní databáze a pak je volat z klientské aplikace. V následujících kapitolách bude popsáno, jakým způsobem lze v programovacím jazyce Java pracovat se SŘBD, zejména však s objektově-relačním modelem databáze Oracle s přihlédnutím na implementaci informačního systému katedry.
2.3.1
Práce s JDBC
Pro práci se SŘBD nám Java poskytuje JDBC. Abychom mohli provést nějakou operaci nad SŘBD, musíme provést následující kroky: 1. Zvolení vhodného JDBC driveru. 2. Registrace JDBC driveru.
20
3. Otevření spojení s databází. 4. Vytvoření příkazu. 5. Vykonání příkazu. 6. Získání výsledku. 7. Uzavření příkazu a výsledku. 8. Uzavření spojení s databází. V následujících kapitolách budou podrobněji popsány výše uvedené kroky.
2.3.1.1
Zvolení vhodného JDBC driveru
Každý výrobce implementace JDBC poskytuje vlastní drivery. Oracle poskytuje několik JDBC driverů, z nichž každý lze použít pro jiný typ klientské aplikace: • Thin driver - 100% Java driver určený pro klientské aplikace, které běží mimo Oracle server. Tento driver nepotřebuje žádný doplňkový software nainstalovaný na klientské straně (např. Oracle klienta). Pro přístup k databázovému serveru používá tento driver Java sockety, což znamená, že se ke komunikaci s databází využívá TCP/IP protokolů. • OCI driver - driver určený pro samostatné klientské aplikace. Na rozdíl od Thin driveru potřebuje ke své funkci nainstalovaného Oracle klienta. Tento driver je napsaný kombinací jazyků Java a C. • Serverovský Thin driver (server-side Thin driver) - je funkcionálně stejný jako Thin driver, ale je určen pro kód běžící uvnitř Oracle serveru, který ovšem pracuje se vzdálenou databází. • Serverovský vnitřní driver (server-side internal driver) - pro kód, který běží uvnitř cílového serveru. Pro samostatné klientské aplikace je tedy nutné použít Thin driver. Proto je tento driver použit i v aplikaci informačního systému katedry.
2.3.1.2
Registrace JDBC driveru
Příklad registrace JDBC driveru výrobce Oracle je následující: DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
21
2.3.1.3
Otevření spojení s databází
Pro otevření spojení s databází se používá metoda getConnection() třídy DriverManager. Parametry této metody jsou: kompletní URL řetězec, jméno uživatele a heslo. URL řetězec má tvar: jdbc:oracle::@. Příklad 2.25: Chceme se připojit k databázi oracle, která naslouchá na TCP portu 1521, pracuje na počítači eviksys s použitím Thin driveru, pro uživatele ger024 s heslem aaaaa. Vytvoření konkrétní instance třídy Connection vypadá například následovně: Connection cn=DriverManager.getConnection("jdbc:oracle:thin:@eviksys:1521:oracle", "ger024", "aaaaa"); Pro potvrzení provedených změn v databázi se užívá příkaz commit. Implicitně se potvrzení provádí automaticky. V následujícím příkladu nejprve vidíme zakázání automatického potvrzování a poté explicitní zadání potvrzení. cn.setAutoCommit(false); cn.commit();
2.3.1.4
Vytvoření příkazu
Příkaz lze vytvořit několika způsoby, které se používají v různých situacích. Způsoby vytvoření příkazu budou popsány dále. První možností je volání metody createStatement() na instanci třídy Connection, která vrací instanci Statement, např. Statement statement = cn.createStatement();, kde cn je instance získaná z předchozího kroku. Druhou možností je využití typu PreparedStatement, který umožňuje provedení příkazu s jedním či více vstupními parametry. Parametrem metody preparedStatement() typu Connection je řetězec, ve kterém je možné místo některých hodnot zadat znak ?. Místo znaků ? se později definují parametry pomocí metod setXXX(), volanými na instanci typu PreparedStatement. Výběr této metody závisí na databázovém datovém typu nastavované hodnoty a na mapování těchto typů na typy jazyka Java, např. hodnotu typu VARCHAR2 nastavíme pomocí metody setString() atd. Je nutné poznamenat, že implementace rozhraní Statement nebo PreparedStatement dodávané výrobci poskytují tyto metody pro další typy poskytované příslušným SŘBD. Například třída OraclePreparedStatement poskytuje metodu setSTRUCT() pro nastavení hodnoty nějakého objektového datového typu. Příklad 2.26: Jestliže chceme v informačním systému katedry vložit nové zařazení zaměstnanců katedry, tedy do objektové tabulky Enlistment table vložit instanci typu TEnlistment. Typ TEnlistment a objektová tabulka Enlistment table jsou definovány: 22
CREATE OR REPLACE TYPE TEnlistment AS OBJECT ( shortcut VARCHAR2(4), name VARCHAR2(20) ); CREATE TABLE Enlistment_table OF TEnlistment; Vytvoření příkazu pro vložení zařazení Profesor se zkratkou prof potom provedeme: PreparedStatement pstmt = cn.prepareStatement( "insert into enlistment_table values (?,?)"); pstmt.setString(1, "prof"); pstmt.setString(2, "Profesor"); Místo prvního symbolu ? v řetězci příkazu se pomocí metody setString() nastaví první parametr. Místo druhého symbolu ? se též pomocí metody setString() nastaví druhý parametr. Obě vkládané hodnoty jsou typu VARCHAR2, který se v Javě mapuje na typ String. Třetí a poslední způsob se využívá pro volání funkcí uložených v databázi a je realizován pomocí typu CallableStatement. Parametrem metody prepareCall() typu Connection je řetězec, ve kterém je možné místo některých hodnot vložit symbol ?. Tato metoda vrací instanci typu CallableStatement. Parametry takové funkce mohou být vstupní a výstupní, kde výstupním parametrem je i návratová hodnota. Vstupní parametry se definují pomocí již popsaných metod setXXX(). Výstupní parametry se definují metodou registerOutParameter(), která je volána na objekt typu CallableStatement. Pro vykonání příkazu se použije metoda executeUpdate() volaná na objekt typu CallableStatement. Výsledek je získán pomocí metod getXXX(), které jsou volány také na objekt typu CallableStatement. Pomocí těchto metod lze vykonat veškeré příkazy jazyka pro definici nebo manipulaci s daty nebo PL/SQL blok. Příslušný příkaz se pouze vloží do řetězce, který je parametrem těchto metod. Příklad 2.27: Chceme provést funkci getAge() se dvěma vstupními parametry (uživatelské jméno a heslo) vracející věk (což je celočíselná hodnota). CallableStatement cstmt = connection.prepareCall("{? = call getAge(?,?)}"); cstmt.registerOutParameter(1, Types.INTEGER); cstmt.setString(1, "ger024"); cstmt.setString(2, "aaaaa");
2.3.1.5
Vykonání příkazu
Po vytvoření příkazu logicky následuje jeho vykonání, které je provedeno pomocí různých metod, které jsou zasílány na instance typu Statement (PreparedStatement, CallableStatement). 23
Příkazy můžeme rozdělit na ty, které vrací jako výsledek množinu výsledků (SELECT), dále na ty, které vrací celočíselnou hodnotu (INSERT, UPDATE a DELETE), která může například značit počet záznamů smazaných příkazem DELETE, a nakonec jsou to funkce, které mohou vracet několik hodnot. Množina výsledků je reprezentována instancí typu ResultSet, která je vrácena metodou executeQuery() typu Statement, jejimž vstupním parametrem je řetězec příkazu, například: ResultSet resultset = statement.executeQuery("SELECT login FROM Student_table"); Metoda execute() objektu typu Statement vykoná příkaz a vrátí hodnotu true, pokud je výsledkem množina výsledků, nebo false, pokud je výsledkem celočíselná hodnota. Pro získání těchto výsledků disponuje Statement dalšími metodami. Metoda executeUpdate() objektu typu Statement slouží pro vykonání příkazů produkujících jako výsledek celočíselnou hodnotu (INSERT, UPDATE a DELETE), která je touto metodou vrácena. Touto metodou jsou vykonávány i databázové funkce definované pomocí typu CallableStatement.
2.3.1.6
Získání výsledku
Jak bylo řečeno v předchozí kapitole, tak některé příkazy vrací množinu výsledků (zejména SELECT), jiné celočíselnou hodnotu (INSERT, UPDATE a DELETE) a databázové funkce mohou vracet více hodnot. Jestliže výstupem příkazu je množina výsledků (tedy vlastně tabulka), pak je nutné z instance typu ResultSet získat jednotlivé sloupce a řádky této tabulky. Instanci typu ResultSet vrací přímo metoda executeQuery(), nebo je možné ji získat zavoláním metody getResultSet() na příslušnou instanci Statement. Pro průchod jednotlivými řádky tabulky výsledku je určena metoda next() typu ResultSet. Jednotlivé sloupce je poté možné získat pomocí metod getXXX(), kde příslušná metoda je volána v závislosti na datovém typu získávané hodnoty a jejím mapování do jazyka Java. Například
while (resultset.next()) System.out.println (resultset.getString(1)); Metoda next() vrátí false pokud je množina výsledků již vyčerpána. V objektově relačním modelu může být datovým typem nějaký objektový typ. V takovém případě je nejprve nutné volat metodu getSTRUCT() pro získání této hodnoty a poté pomocí metody getAttributes() získáme jednotlivé položky instance objektového typu. Metody pro modifikaci databáze vrací celočíselnou hodnotu, která je vrácena přímo metodou executeUpdate() nebo je nutné ji získat z příkazu pomocí getUpdateCount(). Jestliže voláme databázové funkce pomocí typu CallableStatement, pak tento typ disponuje metodami pro získání jednotlivých výstupních parametrů. Například Integer age = cstmt.getInt(1);
24
2.3.1.7
Uzavření výsledku, příkazu a spojení
Pokud příkaz zaslaný na databázi vyprodukoval nějaký výsledek, je nutné jej zavřít metodou close(). Metodou close() je nutné uzavřít i vytvořené příkazy. Zavřením výsledku ani příkazu není uzavřeno spojení s databází a v případě potřeby je nutné jej uzavřít zvlášť. Spojení s databází se uzavírá až po skončení práce s databází a provede se pomocí metody close() volané na objekt typu Connection.
2.3.2
Kompletní příklady
Příklad 2.28: Získání studentských čísel všech studentů z objektové tabulky Student table objektového typu TStudent provedeme: OracleDriver oracleDriver = new OracleDriver(); DriverManager.registerDriver(oracleDriver); Connection cn=DriverManager.getConnection("jdbc:oracle:thin:@eviksys:1521:oracle", "ger024", "aaaaa"); Statement statement = cn.createStatement(); resultSet = statement.executeQuery("select login from Student_table"); while (resultSet.next()) System.out.println(resultset.getString(1)); resultset.close(); statement.close(); cn.close(); Příklad 2.29: Provedení funkce getAge() s nastavením vstupních parametrů a získáním výstupních hodnot provedeme: OracleDriver oracleDriver = new OracleDriver(); DriverManager.registerDriver(oracleDriver); Connection cn=DriverManager.getConnection("jdbc:oracle:thin:@eviksys:1521:oracle", "ger024", "aaaaa"); CallableStatement cstmt = cn.prepareCall("{? = call getAge(?,?)}"); cstmt.registerOutParameter(1, Types.INTEGER); cstmt.setString(1, "ger024"); cstmt.setString(2, "aaaaa"); cstmt.executeUpdate(); Integer age = cstmt.getInt(1); cstmt.close(); cn.close();
25
2.3.3
Práce s objektovou referencí
V objektově-relačním modelu je každé instanci objektového typu přiřazena reference, která jednoznačně identifikuje tuto instanci. Pokud získáme, například pomocí příkazu SELECT, nějakou hodnotu typu REF (tedy referenci na databázový objektový typ), je někdy nutné získat hodnoty atributů instance (tedy provést dereferenci). Příklad 2.30: V informačním systému katedry evidujeme studijní skupiny studentů. Pro evidenci těchto skupin je určen typ TGroup, jehož jednotlivé instance jsou uloženy v objektové tabulce Group table. CREATE OR REPLACE TYPE TGroup AS OBJECT ( name VARCHAR2(4) ); CREATE TABLE Group_table OF TGroup; Referenci na instanci tohoto typu můžeme získat například z objektové tabulky Student table. Jestliže jsme pomocí metody getRef() instance typu ResultSet získali instanci typu Ref, což je javovský typ, na který se mapuje databázová reference, je možné získat jméno skupiny a javovskou reprezentaci databázové reference na skupinu studenta (proměnná ref je typu Ref): Object[] attrib = ((REF)ref).getSTRUCT().getAttributes(); String name = (String)attrib[0]; Ref group = (REF)attrib[10]; Příklad 2.31: V tomto příkladu chceme smazat z tabulky Student table studenta, který je identifikovatelný dle proměnné Ref ref. PreparedStatement pstmt= connection.prepareStatement("DELETE FROM Student_table s WHERE REF(s)=?"); pstmt.setObject(1, ref, OracleTypes.REF); pstmt.executeQuery(); pstmt.close();
2.3.4
SQLData ver. ORAData
Oracle nabízí možnost mapovat uživatelské databázové objektové typy na uživatelské javovské třídy. Je možné využít dvou přístupů: • SQLData - kompatibilní s JDBC a • ORAData - umožňuje snadnější práci s datovými typy SŘBD Oracle. 26
V principu toto mapování přináší pouze snazší práci pro získávání atributů objektů a nahrazuje tak volání několika metod. V této kapitole byly popsány objektově orientované technologie s přihlédnutím k objektověrelačním SŘBD. V kapitole následující bude popsána analýza a návrh databázového schématu informačního systému katedry.
27
Literatura [Apa02] Apache Software Foundation: Xerces Java parser. http://xml.apache.org/xerces-j (květen 2002) [Ben00] Beneš M.: Objektově orientované databázové systémy. Sylaby do předmětu Databázové a informační systémy III. Ostrava 2000. http://www.cs.vsb.cz/benes/ vyuka/dais3/ (květen 2002) [CGI97] Chan M. C., Griffith S. W., Iasi A. F.: 1001 tipů JAVA UNIS Publishing, Brno 1997 [ODMG00] ODMG: The Object Data Standard: ODMG 3.0. ISBN: 1558606475. http://www.odmg.org/standard/odmgbookextract.htm (květen 2002) [OMG00] OMG: UML - Unified Modeling Language. http://www.omg.org/technology/uml/ (květen 2002) [Ora01j] Oracle: Oracle9i JDBC User’s Guide and Reference. Release 9.0.1, June 2001, Part No. A89856-01. http://technet.oracle.com/docs/products/oracle9i/ doc_library/901_doc/java.901/a90211/toc.htm (květen 2002) [Ora01ja] Oracle: Oracle9i Java Developer’s Guide. Release 9.0.1, June 2001, Part No. A90209-01. http://technet.oracle.com/docs/products/oracle9i/doc_library/ 901_doc/java.901/a90209/toc.htm (květen 2002) [Ora01o] Oracle: Oracle9i Application Developer’s Guide - Object-Relational Features. Release 1 (9.0.1), June 2001, Part No. A88878-01. http://technet.oracle.com/ docs/products/oracle9i/doc_library/901_doc/appdev.901/a88878/toc.htm (květen 2002) [Ora01p] Oracle: Oracle9i PL/SQL User’s Guide and Reference. Release 9.0.1, June 2001, Part No. A89856-01. http://technet.oracle.com/docs/products/oracle9i/ doc_library/901_doc/appdev.901/a89856/toc.htm (květen 2002) [Ora01s] Oracle: Oracle9i SQL Reference. Release 1 (9.0.1) June 2001 Part No. A90125-01. http://technet.oracle.com/docs/products/oracle9i/doc_library/901_doc/ server.901/a90125/toc.htm (květen 2002) [Ora01] Oracle: Oracle Documentation. http://technet.oracle.com/docs/products/ oracle9i/doc_library/901_doc/nav/docindex.htm (květen 2002)
66
[Ora02d] Oracle: Oracle JDBC drivers. http://technet.oracle.com/software/tech/java/ sqlj_jdbc/content.html (květen 2002) [Pok00] Pokorný J.: Odkud a kam kráčí databáze. In DATASEM 2000, sborník konference. Masarykova Univerzita v Brně, Brno 2000, pp. 85-104 [Sar97] Šarmanová J.: Teorie zpracování dat. VŠB-TU Ostrava, 1997 [SQL3] ISO,ANSI: SQL3 (ISO-ANSI Working Draft). http://www.inf.fu-berlin.de/lehre/ SS94/einfdb/SQL3/sqlindex.html (květen 2002) [StB00] Stonebraker M., Brown P.: Objektově-relační SŘBD, analýza příští vlny. BEN - technická literatura, Praha 2000 [Sun02d] Sun Microsystems: JDBC Data Access API. http://java.sun.com/products/jdbc (květen 2002) [Sun02j] Sun Microsystems: Java Standard Edition Platform http://java.sun.com/doc/index.html (květen 2002) [Szt00] Szturc, R.: Sylaby přednášek předmětu Internetové http://www.cs.vsb.cz/szturc/courses/INT (květen 2002)
Documentation. technologie.
[Von95] Vondrák I.: Object-Oriented Methods. Sylaby předmětu Objektově orientované metody. Katedra informatiky, VŠB-TU Ostrava, 1995-1997. [Von97] Vondrák I.: Software Engineering. Sylaby do předmětu Softwarové inženýrství. Katedra informatiky, VŠB-TU Ostrava, 1997. [Von97j] Vondrák I.: JavaT M Technology. Sylaby do předmětu Java technologií. Katedra informatiky, VŠB-TU Ostrava, 1997. [W3C98] W3C: W3C Extensible Markup Language (XML). http://www.w3c.org/XML (květen 2002) [YCH99] Chen Y.: Object Oriented Extensions in SQL3. 1999. http://www.cs.uga.edu/ ~ychen/presentation/tsld001.htm (květen 2002)