Zborník vedeckých prác doktorandov a mladých vedeckých pracovníkov “Mladí vedci 2010“
SROVNÁNÍ OBJEKTOVĚ RELAČNÍHO MAPOVÁNÍ S OBJEKTOVĚ ORIENTOVANÝM PŘÍSTUPEM COMPARISON OF OBJECT-RELATIONAL MAPPING WITH OBJECT-ORIENTED APPROACH Jaroslav Ševčík Mgr. Jaroslav Ševčík, Katedra informatiky a počítačů , Přírodovědecká fakulta, Ostravská univerzita v Ostravě, 30. dubna 22 , 701 03 Ostrava,
[email protected] Abstract This thesis compares two different methods to data storage in a database. The first method of object mapping into relational database uses Hibernate framework. The second method uses the object-oriented approach to data storage using object database Caché. This thesis describes how to use and the possibilities of these technologies. Keywords: Java, J2EE, ORM, Hibernate, Caché, Jalapeño 1 Úvod V dnešní době pracuje řada vývojářů na podnikových informačních systémech. Tyto systémy pracují s obrovským množstvím informací, které musí nějakým způsobem uchovávat, zpracovávat a zobrazovat. Jedním z nejpoužívanějších způsobů uchování dat jsou relační databáze. V oblasti programování se přešlo ze strukturovaného k objektovému programování. Objektově orientovaný pohled na svět je člověku více bližší a přirozenější, má plno benefitů a tak usnadňuje způsob programovaní. V relačním a objektově orientovaném přístupu existují značné rozdíly. Bylo prokázáno, že programování kódu, který se zabývá udržením perzistentních dat zabere až 70% času, jenž je na daný projekt vyhrazen. Proto se objevily snahy tento problém řešit. V první řadě bylo potřeba oddělit aplikační logiku od způsobu uložení dat. Tak, aby se programátor nemusel natolik zabývat způsobem uložení dat a mohl se věnovat především práci na aplikační logice. První variantou bylo samotné ukládání do relační databáze co nejvíce zautomatizovat. Což vedlo ke vzniku specializovaných frameworků, které se tento problém snaží řešit cestou objektově-relačního mapování. Druhou variantou bylo nahradit relační databázi za objektovou. Což umožňovalo přímé ukládání objektů s jednoduššími vazbami na programovací jazyk. Článek se zabývá srovnáním těchto dvou přístupů v oblasti vývoje Java aplikací. Byli zvoleni dva zástupci, kteří jsou ve své kategorii asi nejvíce rozšířeni. Za mapování to byl open-source projekt Hibernate a za objektové databáze je tu komerční systém Caché. 2 Objektově relační mapování Technika zvaná objektově-relační mapování, známá též pod zkratkou ORM (Object Relational Mapping), tvoří pomyslný most k překlenutí propasti mezi objektovým a relačním modelem. Překlenout propast mezi oběma modely není lehké. Vychází z myšlenky vytvořit prostředníka, který by řídil automatické transformace z jedné podoby do druhé bez nutnosti, aby programátor musel sám konvertovat objekty do nebo z relačního formátu.
808
Zborník vedeckých prác doktorandov a mladých vedeckých pracovníkov “Mladí vedci 2010“
Relační databáze uchovávají data ve formě dvourozměrných tabulek s řádky a sloupci. Řádek odpovídá jednomu záznamu a sloupec jeho atributu. Sloupec je určen datovým typem, kterých je omezené množství. Atribut může uchovávat jen jednu hodnotu. Vztahy mezi entitami jsou reprezentovány porovnáváním hodnot speciálních polí, nazývaných cizí klíče, s hodnotami identifikátorů záznamů v jiných tabulkách. Objektově orientovaný přístup pohlíží na vše kolem jako na objekt. Objekt má určité vlastnosti a určité operace. Jeho vlastnosti netvoří jen základní datové typy, ale mohou to být i jiné objekty. To umožňuje skládat objekty z jednotlivých částí. Objekty se mohou dědit a tak se rozšiřovat o vlastnosti a schopnosti svých předchůdců. Je to mnohem přirozenější způsob modelovaní reality než v případě relačních modelů. Mnoho podniků provozuje starší informační systémy, které stojí na relačních databázích. Při návrhu nových aplikací pak často zaznívá podmínka, aby se nová aplikace integrovala do stávajícího systému. V takovém případě poskytují ORM nástroje velkou výhodu a těžko zastupitelnou roli. Dalším důležitým faktorem při volbě správy dat hrají možnosti dotazování. Jazyk SQL (Structured Query Language) se těší velké popularitě a jedná se o standard pro manipulaci s daty. Možnosti ORM nástrojů jsou v zásadě omezeny databázovým schématem. Mapování ve srovnání s nativním přístupem přináší určitou ztrátu výkonu. ORM frameworky se tuto ztrátu snaží minimalizovat použitím různých vyrovnávacích pamětí a dalších optimalizací. 2.1 Hibernate Hibernate je profesionální open-source (LGPL v2.1) projekt napsaný v Javě, který představuje ORM řešení pro Javu. Jedná se o middleware, software, který slouží jako konverzní nebo překladatelská vrstva. Hibernate umožňuje teoreticky pracovat s libovolnou databází, ke které existuje JDBC ovladač. Jednotlivé SQL databáze se od sebe liší množstvím svých schopností, syntaxí pro značení identity sloupců, datových typů, dostupných SQL funkcí a používají lehce rozdílné verze SQL jazyka. Proto se v Hibernate všechny rozdíly abstrahovaly do tzv. dialect tříd. Každá podporovaná databáze má tak svůj vlastní dialekt. Těchto tříd je více než 20 a jsou umístěny v balíčku org.hibernate.dialect. Protože navázání spojení s databází může chvíli trvat, Hibernate sám řeší správu připojení tzv. Connection Pool, tedy vytvoření spojení a jeho sdílení mezi aplikacemi. Hibernate lze použit nejen u nových projektů, ale také u již vytvořených. Není fixován jen na platformu J2EE, ale lze ho využít i mimo toto prostředí. Má své vlastní API, ale od verze 3.2 se používá Java Persistence API (JPA), což je standard pro objektově relační mapování a rozhraní pro správu persistence v platformě Java EE 5.0. Je to část specifikace EJB 3.0 (JSR 220), které vychází z původního Hibernate díky účasti dvou jeho tvůrců na přípravě této specifikace. Hibernate umožňuje použit skoro vše co databáze nabízejí. 2.2 Mapování tříd Základem Hibernate mapování jsou třídy označované jako POJO (Plain Old Java Object). Jedná se o jednoduché Java objekty, které neimplementují žádné speciální rozhraní. Tyto objekty pak reprezentují entity, které jsou ukládány do databáze. Tak jako ostatní ORM nástroje i Hibernate potřebuje metadata, které určují způsob transformace dat z jedné reprezentace do druhé. Existují dva základní způsoby zápisu mapovacích metadat. Prvním jsou XML soubory umístěné v adresáři s mapovanými třídami. Obvykle každé třídě odpovídá jeden XML soubor. Druhá varianta je použití anotací
809
Zborník vedeckých prác doktorandov a mladých vedeckých pracovníkov “Mladí vedci 2010“
uvedených přímo v mapovaných třídách. Ve starších verzích Hibernate 2.x bylo možné používat doplněk Xdoclet, který umožňoval vygenerovat XML soubor popisující mapování z metadat zapsaných pomocí speciálních tagů komentáře Javadoc. Později po zavedení anotací do Javy, se začaly používat anotace specifikace EJB 3.0/JPA. Existují také Hibernate extension anotace, které se používají pro zvýšení výkonu, různé optimalizace a speciální mapování. Tyto anotace jsou dostupné z balíčku org.hibernate.annotations. Forma zápisu mapovacích metadat pomocí anotací, je výhodná v tom, že všechna data jsou pohromadě a v případě změn v mapované třídě nehrozí, že vývojář zapomene upravit také jejich mapování. Ve vývojových prostředí Java IDE existuje řada funkcí, které umožňují z existujícího databázového schématu automaticky vygenerovat POJO třídy včetně jejich mapování. Tyto funkce jsou dostupné pro mapování pomocí anotací i pomocí XML souborů. 2.3 Práce s perzistentními objekty Pro správu persistence jsou dostupné dvě API. Nativní Hibernate API, který pokrývá všechny funkce Hibernate a standard podle specifikace Java Persistence API. Obě API poskytují služby jako jsou základní CRUD operace (Create, Retrieve, Update, Delete), vykonávání dotazů (Query), ovládání transakci, správu persistentního kontextu. Hibernate kvůli zvýšení výkonu nerealizuje změny ihned, ale vykonává je po skupinách. Proto, pokud není nastaveno automatické vykonávání, musíme tyto změny potvrdit manuálně. Java Persistence API specifikuje programové rozhraní, pravidla životních cyklů persistentních objektů. Hibernate implementuje tuto část JPA pod názvem Hibernate EntityManager. Práce se standardizovaným rozhraním umožňuje pracovat s jakýmkoliv aplikačním serverem, kompatibilním s EJB 3.0. Avšak JPA funkcionalita tvoří jen podmnožinu toho, co dokáže nativní Hibernate. Lze jej nastavit pomocí konfiguračních souborů nebo přímo v Java kódu. Pro načtení instance z databáze obě API poskytují metody, jejichž parametry tvoří požadovaná třída instance a její primární klíč. Pro vyjádření dotazů v Hibernate existují tři cesty: Hibernate Query Language (HQL) a JPA QL, Criteria API a pojmenované dotazy Hibernate Query Language (HQL) je objektově orientovaný dotazovací jazyk podobný SQL. Obsahuje i stejné klauzule jako SELECT, FROM a WHERE. Na rozdíl od SQL slouží pouze pro vyhledávání objektů. Aktualizace, vkládání a mazání nejsou možné. Je mnohem kompaktnější než SQL. Například využívá vztahy definované pomocí mapování. JPA nabízí jazyk označovaný jako JPA QL. Jedná se o podmnožinu HQL. Criteria API je dostupné jen v rámci Hibernate. Java Persistence API tento způsob načítaní objektů nestandardizovala. Je to alternativa pro dotazovaní perzistentních objektů. Pokud naše dotazy vyjádříme pomocí kritérií, tyto dotazy mohou být lépe čitelné, samo dokumentující a jejich syntaxe bude parsovatelná a ověřitelná při kompilaci. Pokud toto API použijeme, ztratíme část vyjadřovací schopnosti a síly dotazů HQL. Kriteria, která pomocí metody vkládáme mohou být dvojího druhů. Dotazování pomocí kriterií (QBC - query by criteria) – Tento způsob vrací seznam instancí dle definovaných restrikcí (kriterií). Dotazování pomocí příkladu (QBE - query by example) – Tento způsob dotazování nabízí načtení objektů na základě příkladu. Vytvoříme objekt námi hledaného typu s několika známými vlastnostmi. Pojmenované dotazy – Hibernate API i JPA umožňují načítat objekty na základě dotazů, které byly nadefinovány během mapování a označit unikátním jménem na základě, kterého jsou pak volány.
810
Zborník vedeckých prác doktorandov a mladých vedeckých pracovníkov “Mladí vedci 2010“
Mapování objektu do relační databáze ve srovnání s nativním přístupem je pomalejší. Aby se toto zpomalení co nejvíce eliminovalo, využívá Hibernate několik druhů cache. Nevýhodou cache je vyšší paměťová spotřeba, vyšší fragmentace a více dlouho žijících objektů. Komplikací může být také detekce změn. 3 Objektově orientovaný přístup Objektový přístup umožňuje přirozenější reprezentaci složitých struktur reálného světa. Objekty nabízí bohatší datové struktury, které mnohem přirozeněji popisují skutečná data. Návrh objektové databáze tvoří podstatnou část celkového návrhu aplikace, protože objektové třídy aplikace jsou zároveň používané v databázi. 3.1 Caché systém Systém Caché je plně objektově orientovaná databázová technologie. Společnost InterSystems ji uvedla na trh koncem roku 1997. Data v systému Caché jsou uložena v transakčním vícerozměrném databázovém stroji. Caché obsahuje unifikovanou datovou architekturu, která poskytuje jednu společnou vrstvu nejen pro objektový přístup k datům, ale také pro přístup prostřednictvím jazyka SQL. A proto řeší dilema vývojářů, zda použít relační nebo objektové úložiště dat. Dostupná je také projekce objektů do formátu XML souborů. Nabízí podporu datových pohledů a rozhraní pro oba datové modely. Tyto možnosti přístupu umožňují vývojáři vyhnout se časově náročné práci s objektově-relačním mapováním. Objektový model Caché je založen na standardu ODMG (Object Database Management Group) a podporuje tak všechny principy objektových technologii pro ukládaní objektů. Nabízí mnoho pokročilých funkcí včetně vícenásobné dědičnosti. 3.2 Caché třídy Základ tvoří definice Caché tříd, které jsou kompilátorem převedeny do spustitelné podoby. Mohou být generovaný z různých formátů jako jsou programovací jazyk pro definování Caché tříd CDL (Class Definition Language), jazyk pro definici dat DDL (Data Definition Language for SQL) a XML. Caché podporuje neomezený počet datových typů pro vlastnosti objektů. Každý datový typ je reprezentován třídou, každá Caché třída je platným datovým typem. Vývojář může použít základní datové typy Caché nebo si může vytvořit vlastní. Vlastnosti třídy mohou být definovány jako vypočítávané, tedy jejich hodnota se vypočítává za běhu programu. Vlastnosti tříd mohou být také vícerozměrné, ty však mají omezení v podobě, že nemohou být reprezentovány pomocí SQL tabulek. V třídách mohou být definovány také metody s různou funkčností. Jejich kód je možné formulovat v jazycích Caché ObjectScript, Caché Basic a Java. První dva jazyky se překládají do spustitelného kódu Caché a jsou prováděny v rámci běhového prostředí Caché. Java kód je exportován a prováděn v rámci virtuálního stroje Javy. Pro usnadnění tvorby Caché tříd se používá integrované vývojové prostředí Caché Studio. Toto prostředí, kromě samotné podpory vývoje tříd, umožňuje jejich export do různých formátů. Caché třídy je také možné vytvořit na základě importu definic relačních tabulek či přímo relačních databází. Caché umožňuje využívat její objekty také v jazyku Java. Buď objekty řízené aplikací nebo kontejnerem Enterprise JavaBeans. Pro vývoj Java aplikací založených na databázi Caché může vývojář zvolit ze dvou základních způsobů propojení: nativní projekce Caché tříd
811
Zborník vedeckých prác doktorandov a mladých vedeckých pracovníkov “Mladí vedci 2010“
do Java proxy tříd nebo persistence Java tříd pomocí technologie Jalapeño. 3.3 Nativní projekce Caché tříd do Java tříd Jedná se o starší způsob propojení Javy a Caché. Třídy definované v Caché se doplní o informace, které jsou při kompilaci interpretovány. Překladač pak automaticky vygeneruje projekce typu Java proxy tříd. Tyto třídy se vloží do Java projektu a využívají se k práci s databází. K dispozici jsou i projekce pro Enterprise JavaBeans. Tato metoda po Java vývojáři vyžaduje, aby nejprve nadefinoval a vytvořil své datové objekty v Caché. Což předpokládá znalosti prostředí Caché se schopností definovat datový model v tomto prostředí. 3.4 Technologie Jalapeño Od verze 2007 obsahuje databáze Caché nový softwarový modul Jalapeño, což je akronym pro JAva LAnguage PErsistence with NO mapping. Tento modul umožňuje přidat persistenci POJO objektům bez nutnosti objektově-relačního mapování. Vývojář tak může používat své oblíbené Java vývojové prostředí a přitom uchovávat své objekty v databázi Caché. Nemusí ho zajímat, jakým mechanizmem jsou data uchovávána. Nevyžaduje podrobné znalosti prostředí Caché, ani jejich vývojových nástrojů, což významně zkracuje dobu vývoje. Další výhodou přístupu je také lepší výkon, protože není potřeba rozkládat a sestavovat tedy serializovat či deserializovat objekty při ukládání a čtení. Jalapeño lze použít i v kombinaci s relační databází, ale s databází Caché dosahuje nejvyššího výkonu. Jalapeño persistentní knihovna se skládá z komponenty Jalapeño SchemaBuilder což je nástroj, který analyzuje Java třídy a poté vytváří databázové Caché schémata. Druhá komponenta Jalapeño Runtime library je běhová Java knihovna poskytující API pro připojení k databázi, ukládání, získávání dat a dotazování. Pomocí anotací, tedy určitých metadat, doplněných do POJO se nadefinuje jak se mají objekty v databázi uchovat. Anotované POJO Jalapeño SchemaBuilder analyzuje a vytvoří požadované databázové Caché schéma. Anotace neovlivňují chování tříd za běhu programu, určují pouze chování kompilátoru Caché a nejsou povinné. Každá z anotací má různě dlouhý seznam volitelných atributů. Nativní projekce Caché Java tříd i technologie Jalapeño pracují na principu asociace Java objektů v paměti s příslušnými Caché objekty v databázi. Jalapeño Java objekty se však liší od standardních Java proxy objektů použitých v rámci nativní projekce. U Nativní Caché Java projekce se začíná u Caché tříd, ze kterých se později generují Java proxy třídy. Ty jsou navrženy pro těsnou součinnost s Caché. Každá Java proxy třída obsahuje všechny nezbytné nástroje pro interakci s příslušným Caché objektem. Naproti tomu technologie Jalapeño pracuje s již existujícími Java třídami, které nezahrnují tyto metody. Nejprve se z Java tříd vygenerují příslušné Caché třídy a poté se pomocí správce persistence s nimi pracuje. Na správu persistence v technologii Jalapeño se využívá instance třídy ObjectManager. Slouží k manipulaci s perzistentními objekty jako je vytváření, načítaní, aktualizace a odstranění objektů. Lze jej využít také k různému nastavením chování objektů. K vytvoření spojení s databází Caché se využívá JDBC driverů. Správce persistence umožňuje řízení transakcí. Existují také další doplňkové rozhraní pro ostatní činnosti. Rozhraní ExtentManager je určeno pro práci na úrovni rozsahu Caché tříd a nabízí například možnost generování testovacích dat. Pro XML serializaci a deserializaci tříd slouží rozhraní Utilities. Pro načtení instance z databáze poskytuje ObjectManager metody, jejíž parametry tvoří
812
Zborník vedeckých prác doktorandov a mladých vedeckých pracovníkov “Mladí vedci 2010“
požadovaná třída instance a identifikátor. Objekt může být načten také pomocí primárního klíče. Caché umožňuje získávat informace z databáze také na základě SQL dotazů. Caché má svou modifikaci s názvem Caché SQL, která nabízí plnou sadu standardních relačních funkcí. Správce persistence ObjectManager má pro tento úkol vyhrazenu metodu, která vrací výsledek, který splnil kritéria dotazu, ve formě iterátoru. 4 Závěr Cílem této práce bylo srovnat objektově relační mapování s objektově orientovaným přístupem. Oba tyto přístupy, ve srovnání s čistě relačním mapováním, znamenají pro vývojáře obrovskou úsporu jeho drahocenného času. Umožňují mu plně se zaměřit na vývoj samotné funkčnosti aplikace. Nemusí mapovat jednotlivé atributy relačních tabulek do spousty proměnných v Javě. Nemusí se na nejnižší úrovni starat o jednotlivé databázové činnosti. Tyto technologie řeší řadu činností za něj. Značná nevýhoda relačních databází je v potřebě vytváření různých pomocných asociačních tabulek, které reprezentují vazby mezi entitami. Což samotný model dosti komplikuje, snižuje jeho přehlednost a vzdaluje ho od reality. Následné změny nebo rozšíření schématu může u relačních databází znamenat, že se musí celý model přepracovat. To může být dosti nelehké a hlavně časově náročné. Naproti tomu model v objektové databázi je tvořen pouze skutečnými objekty. Nejsou tam žádné pomocné objekty. Model je možné rozšířit pomocí dědičnosti bez potřeby výraznější změny modelu. Proto jsou objektově orientované databáze vhodnější na reprezentaci složitějších modelů. Relační databáze jsou vhodné pro mnoho druhů aplikací, které jsou však charakterizovaný spíše množinou jednoduchých tabulek. Hibernate je standardem pro objektově relační mapování v Javě. Je značně rozšířený a existuje k němu velké množství dokumentace, knih a návodů s příklady řešení. Toto u Caché a především Jalapeño, jako poměrně nové technologie, určitě neplatí. Velkou roli v tom hraje zcela jistě fakt, že relační databáze jsou nejrozšířenější úložiště dat. Může to být také způsobeno tím, že Hibernate je open source projekt na rozdíl od databáze Caché, která je proprietární, respektive komerční produkt. Stejné je to i s existencí různých doplňků a nástrojů, které vývojáři usnadňuji práci. Výhodou Hibernate je jeho nezávislost na databázi. Umožňuje vybrat si databázi s parametry, které nejlépe vyhovují danému projektu. Popřípadě ji mohu změnit s tím, že nebudu muset měnit samotnou aplikaci. Důležitý faktor, který hraje ve prospěch Hibernate je také situace, kdy zákazník trvá na podmínce, že nová aplikace musí využívat databázi již existujícího informačního systému. V tomto případě lze z databáze vygenerovat mapování a databázi používat. Další příjemnou vlastnost nabízí Hibernate v podobě možnosti testovat části aplikace bez potřeby samotné databáze. Hibernate nabízí také několik zajímavých způsobů, jak získat kolekce objektů z databáze. Caché databáze poskytuje výhodu objektového modelu. Také výhodu přístupu k datům jako k objektům nebo k tabulkám pomocí mocného jazyka SQL. To vše v rámci jedné architektury. Tato kombinace z ní děla velmi perspektivní způsob uchovávání dat. Velkou výhodu ve srovnání s Hibernate spatřuji také v menší míře konfigurace před zahájením jejího používáni. Díky tomu lze dříve začít se samotnou prací na aplikaci, což má za následek vyšší produktivitu z hlediska tvorby aplikace. Caché nabízí nástroje pro generovaní schématu ze schématu relační databáze nebo připojené databáze. Snadný export instancí do XML souborů přináší také velkou výhodu. Vývojář není omezen jen datovými typy databáze, ale může si nadefinovat vlastní. Podpora vícerozměrných dat může najít uplatnění v modelování
813
Zborník vedeckých prác doktorandov a mladých vedeckých pracovníkov “Mladí vedci 2010“
složitého systému. Možnost generování testovacích dat a refaktoring schématu Caché tříd bez ztráty již uložených dat může velmi usnadnit vývoj. Technologie Caché Jalapeño umožňuje vývojáři uchovávat a používat své objekty v Caché databázi bez nutnosti znalosti mechanismu ukládání dat. Ovšem jako mladá technologie ještě není tolik vyzrálá jako Hibernate. Hardwarová náročnost Caché je o něco větší něž u MySQL, ale poloviční ve srovnání s Oracle. Je uváděno, že výkonnost je porovnatelná s MySQL a při větší databází (nad 1GB) je výrazně lepší. Výkonnější je také při vykonávání složitějších dotazů a hromadných updatech. 5 Literatura BAUER, Christian; KING, Gavin. Java Persistence with Hibernate. New York:Manning Publications Co., 2007. 841s. 1-932394-88-5 KIRSTEN, W.; IHRINGER, M.;KUHN, M.; ROHRIG, B.. Caché Databáze postrelačního typu a tvorba aplikací. Brno: CP Books, a.s., 2005. 400s. 80-251-0491-5 ŠEVČÍK, J. Srovnání objektově relačního mapování s objektově orientovaným přístupem. Ostrava 2009. 79 s. Diplomová práce. Ostravská univerzita v Ostravě. Recenzent: doc. Ing. František Huňka, CSc., Katedra informatiky a počítačů, Přírodovědecká fakulta, Ostravská univerzita v Ostravě, 30. dubna 22, 701 03 Ostrava,
[email protected]
814