Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
T A R T U Ü L I K O O L
MATEMAATIKA-INFORMAATIKATEADUSKOND
Arvutiteaduse instituut
Tarkvarasüsteemide õppetool
Informaatika eriala
Andres Vilgota
Klassimudelil põhineva objekt-relatsioonilise andmebaasiga
infosüsteemi loomine
Semestritöö
Juhendaja: Jaak Vilo, PhD
Autor: …………………………………… “…..“ detsember 2003
Juhendaja: ……………………………….“…..“ detsember 2003
Õppetooli juhataja: ………………………“…..“ ................ 2003
TARTU 2003
Sisukord
1. Sissejuhatus................................................................................................................. 31.1. Andmebaasidest.................................................................................................... 41.2. Ülesandepüstitus.................................................................................................... 6
2. Kontseptuaalsest mudelist infosüsteemini.................................................................... 72.1. Sõltuvus andmemudeli ja rakenduse vahel............................................................ 72.2. Vahendid objekt-relatsiooniliseks modelleerimiseks.............................................. 8
3. Klassidiagrammist andmebaasiskeemini.................................................................... 103.1. Objekti identifikaator......................................................................................... 113.2. Üks-mitmele assotsiatsioon.............................................................................. 123.3. Mitu-mitmele assotsiatsioon............................................................................. 123.4. Üks-ühele assotsiatsioon.................................................................................. 133.5. Navigeeritav seos/ühesuunaline assotsiatsioon............................................... 143.6. Agregeerimine, kompositsioon......................................................................... 143.7. Pärimine........................................................................................................... 153.8. Variinformatsioon objektides............................................................................ 16
4. Objekt-relatsioonilise andmeteisenduse generaator................................................... 184.1. Eesmärgid............................................................................................................ 184.2. Programmi arhitektuur.......................................................................................... 194.3. Kasutamine.......................................................................................................... 204.4. Klassidiagrammist relatsiooniliste andmebaasitabeliteni..................................... 20
4.4.1. UML seoste kujutamine andmebaasitabelites............................................... 214.4.2. Andmetüübid................................................................................................. 22
4.5. Kontseptuaalsest mudelist Java objektideni........................................................ 235. Objekt-relatsiooniline andmebaasisüsteem. CastorJDO............................................ 246. Põhjalikum näide........................................................................................................ 26Kokkuvõte....................................................................................................................... 30Viited............................................................................................................................... 31Using UML conceptual models to persist Java objects in Object-Relational database.. 32Lisad............................................................................................................................... 33
Lisa 1. Näide tüübiteisenduste XML failist.................................................................. 33Lisa 2. Esialgse XMI faili lihtsustamiseks mõeldud XSL skript.................................... 34Lisa 3. Failide loetelu.................................................................................................. 35
2
1. Sissejuhatus
Tänapäeval on keeruliste tarkvaralahenduste väljatöötamise olulisemateks
nõueteks lahenduse toimimahakkamise kiirus ja lahenduse paindlikkus. Hea lahenduse
tekkimiseks peab olema väga tihe koostöö projekti teostaja ja kliendi vahel, sest pidev
soovide ja vajaduste muutumine on tihtipeale paratamatu. Objekt-orienteeritud
tarkvaralahenduste loomisel on UML [FS99] üheks üha enam populaarsust võitvaks
abivahendiks. UML on modelleerimise keel (ingl. k. Unified Modeling Language), mille
kasutamine võimaldab täpselt väljendada süsteemi kõiki olulisi aspekte, tänu
visuaalsele esitusele on UML diagrammid ja mudelid kergesti mõistetavad. Uueks
suunaks tarkavaraarenduses on aga niinimetatud mudelipõhine arhitektuur [MDA], see
tähendab, et projekte ei kirjutata otseselt koodi tasemel, vaid kasutatakse mudeleid
süsteemi kirjeldamiseks ja (automaatselt) konverteeritakse mudelid koodiks.
Objekt-orienteeritud modelleerimise juures on eristatavad järgmised etapid:
analüüs. (ülesande kontseptsioon, ülesandepüstitus)
standardne süsteemi disain (sealhulgas kirjeldatakse objektid, nende
atribuudid ja omavahelised seosed).
detailne disain (sealhulgas objektide disain, kus detailsuse aste on selline,
et mudel oleks ühilduv konkreetses ülesandes kasutatava
andmebaasisüsteemi ja programmeerimiskeelega. Määratakse atribuutide
tüübid, andmebaasi disainil määratakse/valitakse ka primaarvõtmed,
indeksid, seosed).
teostuse etapp (disain on piisavalt täpne ja otse konverteeritav
konkreetese ülesande lahendamiseks kasutatavasse
programmeerimiskeelde ja andmebaasistruktuuri. Vajadusel muudetakse
mudelit.).
testimine, hooldus.
3
UML on de facto standard tarkvara spetsifikatsioonide loomisel, tarkvara
visualiseerimisel, disainimisel ja dokumenteerimisel. UML eesmärk on lihtsustada
tarkvaraarendust, UML populaarsus on suuresti tingitud asjaolust, et tema vahenditega
saab modelleerida praktiliselt kõike. UML defineerib kokku 12 erinevat tüüpi diagramme,
jagatuna kolme kategooriasse: struktuuridiagrammid (sealhulgas ka klassidiagrammid),
käitumisdiagrammid ja mudelihaldusdiagrammid. Andmebaasispetsialistid saavad
kasutada UML-i andmebaasi disainiks, firmajuhid organisatsioonilise struktuuri
selgitamiseks jne. Ühe ja sama keele ning vahendi kasutamine pealtnäha täiesti
erinevate probleemide juures võimaldab palju paremat suhtlust eri meeskondade vahel.
Kuidas aga jõuda ülesandest lahenduseni? Üheks võimaluseks on jagada ülesande eri
osadega tegelejatele kätte paberileht skeemide ja diagrammidega… Kui aga kui UML
on piisavalt võimas vahend kirjeldamaks erinevaid eesmärke, võimaldades sealjuures
nende ülesannete ühendavaid jooni arusaadavalt selgitada kõikidele osapooltele, siis
miks mitte kasutada UML universaalsust ja näidata, et üpris lihtsasti on võimalik (mingit
UML-i mõistvat programmi kasutades) automaatselt lahendada mitu probleemi korraga.
1.1. Andmebaasidest
Tänapäevase infosüsteemi keskseks osaks on kindlasti andmebaasid. Seni väga
levinud relatsiooniliste andmebaaside kõrval hakkavad üha enam kasutust leidma
objekt-orienteeritud andmebaasid, kuna neid on OO programmeerimiskeeltes oluliselt
loomulikum kasutada. Objekt-orienteeritud andmebaasina võib vaadelda ka
niinimetatud objekt-relatsioonilist andmebaasi. Objekt-relatsioonilises andmebaasis
hoitakse andmeid relatsioonidena, kuid relatsioonidele on ehitatud objektivaade, see
tähendab, et läbi teatud teisenduste paistavad andmed objektidena, mitte
relatsioonidena.
On palju tootjaid, kelle andmebaasisüsteemid ongi objekt-relatsioonilised, näiteks
PostgreSQL, Oracle9i, Caché, FirstSQL, … [ORVendors], selles semestritöös aga
mõtlen ma edaspidi objekt-relatsioonilise andmebaasi all relatsioonilist andmebaasi
koos vastava andmeteisendajaga (ingl. k. object-relational mapping tool). Sellisteks
4
teisendajateks on näiteks Castor, CocoBase, Hibernate, LiDO, … [ORMapping].
Sisuliselt annavad relatsioonilised andmebaasid koostöös sellise teisendajaga
tulemuseks samuti objekt-orienteeritud andmebaasi. Erinevalt objektandmebaasidest on
andmed ikkagi täiesti tavalises relatsioonilises andmebaasis, mis võimaldab vajaduse
korral lihtsat ligipääsu tavaliste SQL päringutega.
Eelnimetatud teisendused objektivaate ja relatsioonilise vaate vahel pole väga
lihtsad, näiteks tuleb relatsioonilises baasis kuidagi võimaldada objekt-orienteeritud
maailmas nii tavapärast nähtust nagu pärimine. Ometigi on sellised teisendused
olemas, teisenduste eest vastutab objekt-relatsiooniline andmeteisendaja, näiteks
Castor [Castor]. Kasutades Castorit on Java keskkonnas töötades võimalik lihtsasti
saavutada ligipääs objektide püsiesitusele mõnes relatsioonilises SQL andmebaasis.
Seda eeldusel, et andmeteisendajale on eelnevalt teada antud, mismoodi üht ja sama
objekti esitada relatsioonilisel kujul ja mismoodi objektkujul.
Huvitava võimalusena võikski UML universaalsust üritada näidata seoses
infosüsteemis liikuva infoga. Kuidas hoitakse andmeid? Andmete tekkimise-muutumise
etapis hoitakse andmeid Java objektidena mälus. Kuna enamasti on siiski tarvis
andmeid ka pikemat aega säilitada, siis tundub mõistlik olevat andmebaaside
kasutamine. Kui nüüd aga olukorda vaadelda veidi üldisemalt, siis on meil infosüsteemis
andmeid kahel eri kujul, ometigi vastavad need kujud ühele ja samale kontseptuaalsele
klassimudelile.
5
1.2. Ülesandepüstitus
Käesoleva semestritöö eesmärk on uurida ja automatiseerida UML-põhist tarkvara
loomist: luua abivahend, mis genereeriks UML klassidiagrammi põhjal automaatselt
vastavad Java klassid, klassidele ja klassidevahelistele seostele vastavad tabelid
relatsioonilises andmebaasis ning kirjelduse, mis võimaldaks andmete teisendamist
Java objektide ja andmebaasi vahel.
Semestritöö praktiline eesmärk on kirjutada Java programm, mis UML
klassidiagrammi põhjal genereeriks nn püsiesitust võimaldavaid Java klasse (ingl. k.
persistent classes), kasutades selleks relatsioonilist andmebaasi. Selle asemel aga, et
suhelda relatsioonilise andmebaasiga otse, kasutan objekt-relatsioonilist
andmeteisendajat. Semestritöös valmiv tööriist loob andmeteisendajale vajaliku
kirjelduse, kuidas konkreetseid objekte teisendada relatsioonilisele kujule ja kuidas
sellest taas saada Java objekt. Põhimõtteliselt aitab tööriist automaatselt sooritada
tarkvara andmemudeli detailse disaini ja teostuse etapid, pärast andmemudeli
modelleerimist saab kasutaja kiiresti hakata tegelema juba infosüsteemi juhtimisloogika
arendamisega.
6
2. Kontseptuaalsest mudelist infosüsteemini
Infosüsteemi rakendusmudel (ingl. k. application model) on sisuliselt vaade
infosüsteemis kasutatavatele klassidele. Andmemudeliks (ingl. k. data model)
nimetatakse reaalse andmebaasiskeemi kirjeldust. Rakendusmudeli osasid klasse peab
olema võimalik esitada püsivalt, seega püsiesitust nõudvad klassid (ingl. k. persistent
classes) tuleb siduda andmemudeliga. Kui andmemudel koostatakse infosüsteemi
kontseptuaalse mudeli põhjal andmebaasispetsialistide poolt ning rakendus
programmeerijate poolt, siis varem või hiljem tekivad paratamatult probleemid nende
omavahelise ühildumisega [Amb03]. Kui aga kogu süsteem alati kindlate reeglite alusel
ühest kindlast mudelist teha, siis seda muret ei ole.
2.1. Sõltuvus andmemudeli ja rakenduse vahel
Kui infosüsteemile esitatavate nõuete seas on võimalikult suur paindlikkus ja
sõltumatus kasutatavast platvormist, siis on oluline vaadata eri komponentide
omavahelist sõltuvust. Kui infosüsteem on tugevalt seotud platvormispetsiifiliste
komponentidega, siis muutub infosüsteem raskesti uuendatavaks. Vaatleme kuidas on
teineteisest sõltuvad andmebaas ja Java rakendus.
Relatsioonilise andmebaasi ja objekt-orienteeritud rakenduse korral on tugevad
sõltuvused andmebaasiskeemi ja rakenduse vahel. Näiteks andmebaasiskeemi
muutmise korral tuleb rakenduses hakata ümber kirjutama SQL päringuid, veelgi enam:
näiteks DB2 vahetamisel MySQL vastu tuleb teha tööd kohandamaks rakendust uue
SQL dialektiga. Kui DB2 korral oli mingi osa andmeloogikat kirjutatud
andmebaasisüsteemi, siis nüüd tuleb palju loogikat kirjutada rakendusse. Seega
muutuvad nii andmemudel kui ka kõik rakendused.
Objektandmebaasides on võimalik andmebaasi sisse kirjutada keerulisi
käitumismalle ja isegi peita tegelik andmete esituse viis, aga seeläbi süvendatakse
andmemudeli ja rakendusmudeli vahelist sõltuvust. Sisuliselt liigub rakenduste loogika
andmebaasi loogikaks. Kui aga ühe rakenduse jaoks on tarvis andmebaasi muuta, siis
andmebaasi muutmisest sõltuvad ka kõik ülejäänud rakendused. Seega andmemudel ja
7
rakendusmudel on teineteisest tugevalt sõltuvad. Tugev sõltuvus aga tähendab seda, et
muudatuste tegemine koodi ühes osas võib tähendada paljusid muudatusi mujal.
Objekt-relatsioonilise andmebaasi ja objekt-orienteeritud rakenduse korral
sõltuvad rakenduse andmemudel ja andmebaasisüsteemi andmemudel teineteisest
vaid kaudselt, läbi andmeteisenduse (ingl. k. mapping). Teisendus ise sõltub nii
andmebaasisüsteemist kui ka rakendusest, kuid sellele vaatamata on teisendus tänu
oma lihtsale esitusele (XML fail) kergesti muudetav. Rakendusmudelitest sõltumatult
saab muuta andmebaasiskeemi (näiteks jõudluse huvides de-normaliseerimine),
kajastades vajadusel andmebaasiskeemi muutused andmeteisenduses. Kui on tarvis
muuta rakenduses kasutatavat mudelit, siis muudame teisendus-dokumendis
objektivaadet, andmebaasiskeemid võivad jääda täiesti puutumata.
2.2. Vahendid objekt-relatsiooniliseks modelleerimiseks
Umbrello UML Modeller [Umbrello] on vabavaraline avatud lähtekoodiga UML
diagrammide joonistamise programm KDE keskkonna jaoks, alates KDE versioonist 3.2
kuulub ta ka KDE standardpaketti. Umbrello on väga lihtsasti kasutatav, ei nõua arvutilt
palju ressurssi (mida teevad paljud teised, nt Poseidon, ArgoUML) ja mis peamine, ei
nõua ka ressurssi rahakotis (Rational Rose vahendite hinnad algavad tuhandetest
dollaritest).
UML laiendamine objekt-relatsioonilise süsteemi disainiks. UML kui
modelleerimise vahend võimaldab paindliku laiendamise võimalusi stereotüüpide (ingl.
k. stereotypes), siltväärtuste (ingl. k. tagged values) ja kitsenduste/tõkete (ingl. k.
constraints) kasutamise näol [MVC01]. Selliseid laiendusvõimalusi on välja pakutud ka
objekt-relatsiooniliseks modelleerimiseks, mingit ühtselt aktsepteeritavat standardit aga
olemas ei paista olevat. Stereotüüpide kasutamise üks loomulik võimalus oleks uute
struktureeritud andmetüüpide defineerimise võimalus : UML-is saab põhimõtteliselt
defineerida uusi andmetüüpe, nt aadressi tüüp. Siis klassidiagrammis saaks Inimene
klassis kasutada atribuuti aadress ja panna atribuudi tüübiks Aadress. Niiviisi paraneks
ka klassidiagrammi ülevaatlikkus.
8
Castor on vabavaraline andmete sidumise raamistik (ingl. k. data binding
framework) Java jaoks. CastorJDO tegeleb relatsioonilise andmebaasi ja Java vahelise
sidumisega, CastorXML aga Java objektide ja XML vahelise sidumisega. Mõlemad
võivad kasutada ühte ja sama andmeteisenduse faili, seega kui vastav fail on olemas
java ja relatsioonilise andmebaasi sidumiseks, siis on sinna väga lihtne lisada ka mõned
väljad objektide XML-kuju saamiseks. Castori eelis avaldubki selles, et ta suudab Java
objekte esitada nii relatsioonilises andmebaasis kui ka XML dokumentidena, paljud
teised lahendused tegelevad ainult ühega neist korraga, mis tähendab, et infosüsteemi
toimimiseks tuleb kasutada veel täiendavaid vahendeid. Objekt-relatsiooniline
andmebaasisüsteem kasutades objekt-relatsioonilist andmeteisendajat Castor:
9
LiDO [ORMapping] on samuti objektide relatsioonilisse andmebaasi salvestamist
võimaldav Java põhine vahend, tema peamine erinevus Castorist on võimalus nn
äriobjektid jätta täiesti puutumatuks andmebaasiga seonduvast variinformatsioonist.
Infosüsteemi programmeerija ei pea absoluutselt tegelema ühegi lisaatribuudiga oma
objektides, ta lihtsalt määrab andmeteisenduses (samuti XML-põhine, nagu Castorilgi)
milliseid objekte ja milliseid väljasid ta andmebaasi salvestada tahab. Tegelikult on
muidugi objektide puutumatus näiline, LiDO kasutab koodi järelprotsessimist (ingl. k.
bytecode processing), st pärast Java koodi kompileerimist võtab LiDO uuesti vastavad
class-failid lahti ja paneb objektid implementeerima vastavaid JDO interfeisse.
Hibernate [ORMapping] on samuti vabavaraline, väga populaarne ja põhjalik
tööriist relatsioonilise andmebaasi ja Java sidumiseks. Ka Hibernate kasutab
analoogilist XML-formaadis andmeteisendusfaili, kuna aga see on piisavalt erinev
Castori vastavast XML-ist, siis selles semestritöös valminud tööriist (veel) Hibernate
jaoks ei sobi.
JDO (Java Data Objects) – arendajaks Sun – hulk üldisi Java interfeisse
objektidele püsiesituse (ingl. k. persistence) võimaldamiseks. JDO on kujunemas
standardiks objektidele püsiesituse andmisel. Huvitaval kombel Castor ei järgi Sun-i
JDO standardit, vaid kasutab enda väljatöötatut (vaidlused JDO kui “kaubamärgi” looja
üle käivad ExoLab grupi ja Sun-i vahel vist siiani...).
3. Klassidiagrammist andmebaasiskeemini
Käesolevas peatükis kirjeldan üldisi võimalusi objektide ja nendevaheliste seoste
hoidmiseks andmebaasis. Peatükis 6 näitan lähemalt tulemusi, mida annab
andmebaasitabelite generaator.
Klassidiagrammist andmebaasitabelite saamine on selle semestritöö keerulisim
osa. Üldised reeglid klassidiagrammist andmebaasitabelite tegemiseks on järgmised:
10
iga klass kujutub üheks tabeliks, iga klassi (lihttüüpi) atribuut kujutub tabeli veeruks,
klassidevaheliste seoste põhjal lisatakse tabelitesse vastavad väljasid mis viitavad
teistele tabelitele. Vastavad ilmekamad näited on toodud peatükis 6. Järgnevalt aga
mõned olulisemad põhimõtted, mille põhjal ja tänu millele saame objekte ja
klassidevahelisi seoseid andmebaasis hoida. Vaatleme ka enamlevinud võimalusi,
kuidas UML seosetüüpe andmebaasis kajastada.
3.1. Objekti identifikaator
Objekte eristab üksteisest objekti identifikaator. Nii nagu Javas on igal objektil
süsteemisisene identifikaator (oid), nii peab ka igal andmebaasis oleval objektil olema
mingisugune identifikaator, selleks on tabeli primaarvõti. On kombeks mitte märkida
identifikaatorvälja atribuudina klassidiagrammile, kontseptuaalses mudelis on vaid
klassid, nende sisulised atribuudid ja klassidevahelised seosed. Kuna aga andmebaasis
on siiski tarvis ridu üksteisest eristada, siis tuleb objektidele lisada andmebaasi
identifikaator ehk tabeli primaarvõti.
Sisuliselt tähendab see disainitud andmemudeli muutmist, sellesse lisaväljade
tekitamist. Miks aga muuta disaini? Infosüsteemi disainer võiks ju ise saada määrata,
milline väli sobiks klassi objekte identifitseerima. Näiteks üliõpilaste andmebaasi korral
võiks ta tahta üliõpilase matriklinumbrit määrata primaarvõtmeks. Või inimese
isikukoodi. Siiski võivad need atribuudid olla piisavalt ebausaldusväärsed või muul viisil
sobimatud identifikaatoriks. Inimese isikukood võib olla valesti sisestatud,
kasutajatunnust süsteemis on võib-olla tarvis muuta jne. Süsteemist sõltumatu
identifikaator vabastab meid koheselt sellistest probleemidest, lisaks saame
identifikaatorvälja valida just andmebaasile sobivat (täisarvulist) tüüpi:
11
UML SQL
3.2. Üks-mitmele assotsiatsioon
Kõige kergem on relatsioonilises andmebaasis kajastada üks-mitmele seost. Üks-
mitmele seost saab väljendada lisades ühte tabelisse välisvõtme (ingl. k. foreign key),
mis viitab teise tabeli primaarvõtmele.
UML SQL
3.3. Mitu-mitmele assotsiatsioon
Mitu-mitmele seost klassidiagrammis eritatakse relatsioonilises andmebaasis
kolme tabeliga. Lisaks seoses otseselt osalevatele tabelitele tuleb teha seost hoidev
assotsiatsioonitabel. Sisuliselt lõhutakse üks mitu-mitmele seos kaheks üks-mitmele
seoseks. Seosetabel hoiab viitasid kummagi seoses osaleva tabeli primaarvõtmele.
Andmebaasi jõudluse huvides tuleks lisada ka indeksid:
12
UML SQL
3.4. Üks-ühele assotsiatsioon
Kuna igale klassile lisati andmebaasi jaoks spetsiaalne dbid väli (kõikide klasside
jaoks ühesugune), siis üks-ühele seos nt inimese ja tema isikukoodi vahel väljendub
andmebaasis vastavate tabelite dbid väljade võrdsuses.
UML SQL
13
3.5. Navigeeritav seos/ühesuunaline assotsiatsioon
Ühesuunaline seos ehk navigeeritav assotsiatsioon väljendub andmebaasis täpselt
samamoodi, nagu vastav kahesuunaline seoski. Relatsioonialgebra omaduste tõttu on
alati võimalik mistahes seoseid vaadelda kahesuunalistena, see tähendab, et
andmebaasi tasemel ei ole meil ühesuunalisi seoseid, nagu on UML-is ja põhimõtteliselt
ka Javas. Kui me saame leida milliseid fotosid on fotograaf teinud, siis saame ka leida
iga foto kohta tema autori. Ühesuunalist seos väljendatakse klassidiagrammis noolena.
UML SQL
3.6. Agregeerimine, kompositsioon
Üks modelleerimisel põhitähelepanu vajavaks tingimuseks on seoses osalevate
andmeolemite omavahelise hierarhia määratlemine, st ühtede objektide olemasolu võib
sõltuda mõne teise objekti olemasolust. Sõltuvat objekti nimetatakse siis nõrgaks
olemiks. Samas võivad seotud objektid eksisteerida teineteisest täiesti sõltumatult,
selliseid objekte nimetatakse tugevateks olemiteks. UML klassidiagrammis saab
14
selliseid sõltuvusi edukalt väljendada, selleks on kasutada seosetüübina agregeerimine
ja kompositsioon. Agregeerimine: üks klass (mis väljendab seose tervik-poolset objekti)
sisaldab hulka teise klassi elemente (osa-poolsed objektid). Klassidiagrammis
väljendatakse agregeerimist klassidevahelise joonega, mille tervik-poolses otsas on
seest tühi teemant. Kompositsiooni korral eksisteerib klasside vahel samuti tervik-osad
suhe, aga osad ei eksisteeri ilma tervik-poolse objektita. Kompositsioon, mis ongi oma
olemuselt kitsendustega agregeerimine, väljendatakse diagrammil joonega, kus seose
tervik-poolses otsas on seest täis teemant. Andmebaasis ei ole otseselt võimalik
väljendada agregeerimine ega ka kompositsiooni, parim mis me teha võime, on
kompositsiooni korral määrata not null kitsendus sõltuva tabeli sellele veerule milles
on viidad tervik-poolsetele objektidele.
UML SQL
3.7. Pärimine
Klasside pärimise kujutamiseks andmebaasis on peamiselt kaks võimalust: kas
kasutada mitut tabelit või ühte tabelit. Mitme tabeliga ehk nn relatsiooniline pärimine,
kus üks tabelitest hoiab baasinformatsiooni ja teine lisainformatsiooni, näeb välja niiviisi:
alamklassi rollis olevale tabelile lisatakse viide ülemklassi primaarvõtmele, selle järgi on
võimalik alamklassis teada saada kõigi päritud väljade väärtusi. Näiteks kui Fotograaf
15
pärineb Inimesest siis tabelis inimene on baasinfo inimese kohta, tabelis fotograaf aga
fotograafile omane lisainfo, näiteks tööstaaž või tema kasutuses olev tehnika. Teine
võimalus pärimise kajastamiseks on de-normaliseerimine. Kui alamklassil on vaid
mõned lisaatribuudid, siis võib olla mõttekas andmebaasitabeleid de-normaliseerida
lisades alamklassi atribuudid ülemklassi tabelile, sealjuures lubades lisatud veergudel
olla ka väärtustamata (null). Ainult ühe tabeli kasutamisega mitme eritüübilise objekti
salvestamiseks on võimalik saavutada päringutele kuluva aja vähenemine ja andmetele
ligipääsu paranemine (ühe lihtsa päringuga terve objekt). Samas ei ole enam võimalik
alamklassi atribuutidele rakendada not null kitsendusi. Sel juhul on soovitatav
tabelisse igale reale lisada ka selline lisaveerg, mis näitaks millist tüüpi objektiga on
tegu.
UML SQL
Kahe tabeliga, relatsiooniline pärimine:
Ühe tabeliga:
3.8. Variinformatsioon objektides
Objektide andmebaasis säilitamiseks on tarvis teada sellist infot, mis iseenesest ei
kuulu andmemudeli juurde, küll aga kuulub vastavate andmebaasitabelite juurde.
Peamiselt mõeldakse siinkohal eri objekte andmebaasis eristavaid dbid-väljasid, aga ka
16
näiteks eelmises lõigus kirjeldatud objekti tüübi määratlejat. Samas võiks
variinformatsiooniks lugeda ka klassi seoseid teise klassiga. Selleks, et üks objekt
andmebaasi salvestada, peavad ka teised temaga seotud objektid olema salvestatavad.
See tähendab, kõik kohustuslikud väljad peavad olema väärtustatud kõigis objektides,
mis on esimesega seotud. Variinformatsiooniks loetakse ka nt igale objektile lisatud
tõeväärtus-tüüpi atribuuti, mis iseloomustab, kas see objekt on juba andmebaasi
salvestatud või on ta ainult mälus (näiteks äsja loodud aga salvestamata objekt).
17
4. Objekt-relatsioonilise andmeteisenduse generaator
Selles peatükis kirjeldan esmalt käesoleva semestritöö käigus valmistatud
programmi tööpõhimõtet ja üldist arhitektuuri, seejärel on kasutamisjuhend (peatükk
4.3), alles seejärel selgitused ja näited sellest, milliseid konkreetseid lahendusi
programm kasutab andmebaasitabelite ja Java klasside tegemisel. Programmi peamine
kasulikkus peitub iseenesest andmeteisenduse kirjelduse loomises Castori jaoks, kuid
kuna see kirjeldus on suhteliselt lihtsasti mõistetav, siis selles peatükis me seda kuigi
põhjalikult ei käsitle, andmeteisenduse näide on peatükis 6.
4.1. Eesmärgid
Kirjutada programm, mis suudaks sisendiks võtta Umbrello 1.2 klassidiagrammi
(XMI failina) ja genereerida selle põhjal tarvilikud kirjeldused CastorJDO
andmeteisendajale, samas genereerida ka andmebaasitabelid ja Java klassid.
Loomulikult on tarvilik, et genereeritud failid oleks omavahel nii-öelda „kooskõlas“, see
on ka üks põhjustest, miks me ei saa kasutada suvalise modelleerimispaketi
koodigeneraatoreid:
18
4.2. Programmi arhitektuur
Umbrello 1.2 salvestab oma klassidiagrammid XMI (lühend sõnadest XML
Metadata Interchange) standardil põhinevas formaadis. XMI formaat on välja töötatud
OMG (Object Management Group) poolt ja on mõeldud mudelite ja meta-andmete
andmevahetuse standardiseerimiseks. XMI ise on tegelikult XML fail.
Umbrello XMI sisaldab ka palju Umbrello-spetsiifilist infot, seega kirjutasin väikese
xsl-skripti (vt Lisa 2), mis eemaldab algupärasest XMI-st koodi genereerimise jaoks
ebaolulise info.
Kuna Castor oskab suurepäraselt esitada objekte ka XML failidena (ja ka XML faili
objektidena), siis kasutame Castorit lihtsustatud XMI-st info lugemiseks klassidiagrammi
klasside, klassi atribuutide ja operatsioonide ning seoste kohta. Muide analoogiliselt
kasutame Castorit veel päris tihti: näiteks tüübiteisenduste (lähemalt andmetüüpidest
peatükis 4.4.2) lugemiseks, andmebaasiühenduse konfiguratsioonifaili loomiseks
Castorile (vt ptk 6 lõpp) ning ka teisenduse XML faili tekitamiseks.
Peamised klassid programmis on MappingGenerator ja AssociationHandler,
esimene neist tegeleb üldise programmi juhtimisega (loeb sisse info klasside ja seoste
kohta, kirjutab tulemusi vajalikesse failidesse, jne.), teine lisab vastavat UML seose
tüübile atribuute seoses osalevatesse klassidesse ja loob andmeteisendaja jaoks
vajaliku kooskõlalised seosed Java atribuutide ja andmebaasitabeli veergude vahel.
Programmi tööpõhimõte on lihtne: esiteks vaatame läbi kõik klassid, lisame neile
andmebaasi-identifikaatori ja kõik lihtatribuudid (tüübiteisenduse faili põhjal), seejärel
vaatame läbi kõik seosed ja vastavalt seose iseloomule lisame atribuute Java
klassidesse ja/või andmebaasitabelitesse.
19
4.3. Kasutamine
Eeldame, et kasutaja on joonistanud diagrammi ja installeerinud Castori (st lisanud
vastavad jar-failid CLASSPATH-i). Esialgu on programm graafilise kasutajaliideseta,
see-eest on selle kasutamine väga lihtne. Enne programmi käivitamist tuleb
konfigureerida soovitud andmebaasiühendus, selleks on etc/mapper.properties fail.
Konfiguratsioonifailis tuleb ka määrata kataloog kuhu projekte genereeritakse. Kataloog
peab enne programmi kasutamist olemas olema.
Kasutamine käsurealt :
> java mapper.MappingGenerator joonistatudDiagrammiFail.xmi projektinimi
Programm teeb projektide kataloogi projektinimi–nimelise kataloogi, kuhu tekivadfailid :
mapping.xml – teisendusfail
database.xml – andmebaasiühenduse konfiguratsioon Castori jaoks
create_tables.sql – andmebaasitabelite DDL
drop_tables.sql – konkreetse projekti andmebaasitabelite kustutamise DDL
igale klassidiagrammi klassile vastav *.java fail. (kui diagrammil onklassidele märgitud ka paketinimi, siis tehakse failid vastavatessealamkataloogidesse)
Edasi on juba lihtne, tuleb vaadata mõnda näidet Castori koduleheküljelt või näidet
peatükist 7. Süsteem on töövalmis!
4.4. Klassidiagrammist relatsiooniliste andmebaasitabeliteni
See peatükk annab ülevaate sellest, kuidas minu semestritöös valminud tööriist
andmebaasitabeleid genereerib. Lihtsuse ja andmeteisenduse XML-i ilmekuse mõttes
kasutame andmebaasis kõikvõimalikes nimedes ainult väiketähti. Andmebaasitabel
20
saab nime klassi nime järgi. Klassidiagrammi klassi ja andmebaasitabeli vahel on üks-
ühene seos, kuigi erijuhtudel (näiteks rekursiivne mitu-mitmele seos) võib üks klass olla
ka esitatud kahe või enama tabelina. Tabelile primaarvõtmena märgime objekti
andmebaasi-identifikaatori ehk välja „dbid“, mis on sisuliselt samasugune unikaalne ja
igale objektile automaatselt genereeritud väli nagu ka süsteemne oid (ingl. k. object
identifier) Javas, ainult et tehnilistel põhjustel ei ole see identifikaator tekitatud koodis
niivõrd varjatud: nimelt näeme hiljem, et igasse Java objekti tuleb tekitada ka
andmebaasi-identifikaatorile vastav väli.
On mitmeid olukordi kus tuleb otsustada millist strateegiat kasutada. Näiteks
milliseid andmetüüpe kasutada Javas, milliseid andmebaasis; millal on põhjendatud
kitsenduste kasutamine (ilmselt ei ole mõttekas panna igale veerule kitsendust not
null), millal kasutada relatsioonilist pärimist ja millal mitte. Selliste otsuste tegemisel
olen lähtunud kasutajamugavust suurendavatest põhimõtetest. See tähendab, et kui on
võimalus valida, kas lasta kasutajal kirjutada palju koodi ja lubada vähe funktsionaalsust
või olla piisavalt üldine, et lubada rohkem võimalusi, siis alati lubame rohkem võimalusi.
Kitsendusi kasutame vähe, osalt ka seetõttu et spetsiifiliste kitsenduste rakendamine on
liiga keeruline või võimatu.
4.4.1. UML seoste kujutamine andmebaasitabelites
Tavapäraselt lisatakse näiteks üks-mitmele seose korral ühele tabelile välisvõti
(ingl. k. foreign key), sellega seoses ka välisvõtme kitsendus (ingl. k. foreign key
constraint). Kuna aga meie eesmärk on saavutada objekt-relatsiooniline andmebaas
muuhulgas ka võimalikult väikese sõltuvusega konkreetsest relatsioonilisest
andmebaasisüsteemist, siis meie seda kitsendust lihtsalt ei lisa, pealegi hoolitseb
seoste korrektse haldamise eest niikuinii objekt-relatsiooniline andmeteisendaja
(Castor).
UML-is on ühe seose tüübina võimalik kasutada agregeerimist, kuna aga
relatsioonilises andmebaasis pole otseselt võimalik väljendada ei agregeerimist (ega ka
kompositsiooni), siis kasutame agregeerimise väljendamiseks samu meetodeid, kui
tavalise UML assotsiatsiooni korral. Siiski, kompositsiooni korral saame kasutada
21
Castori võimalust määrata üks klass sõltuvaks teisest klassist (selleks on andme-
teisenduses atribuut depend), niisiis toimib kompositsioon Castori tasemel. See
tähendab, et kui tervik-poolne objekt eemaldatakse, siis kustutatakse andmebaasist ka
temaga seotud osa-poolsed objektid. Ka vastupidine toimib, st Castor ei luba
andmebaasi luua osa-poolset objekti, kui ta ei ole seotud tervik-poolse objektiga.
Pärimisseose väljendamiseks kasutan niinimetatud relatsioonilist pärimist, kus
alamklass kajastub andmebaasis kahe tabelina: eraldi tabelis lisainfo alamklassi
objektide kohta ja ülemklassi info üldisemas tabelis (vt peatükk 3.7).
4.4.2. Andmetüübid
Klassidiagrammi igast atribuudist saame tabelisse juurde ühe veeru, veeru nimeks
on klassidagrammi atribuudi nimi, veeru tüübi saame, kui „tõlgime“ diagrammis märgitud
atribuudi Java tüübi sql-tüüpi. Nii näiteks Java tüübile Integer vastab MySQL-is int(11),
Java tüübile String võib vastavusse seada varchar(255), Java tüübile Boolean char(1)
(tõese väärtuse korral Y ja väära korral N), Java Date tüübile timestamp jne. Selline
tõlkimine võib kohati tunduda täiesti meelevaldne. Näiteks ei või me andmebaasitabelite
genereerimisel kuidagi teada, kas disainis märgitud "string" on mõeldud hoidma inimese
eesnime (tüüpiliselt alla 20 tähemärgi) või näiteks 5MB suurust XML faili. MySQL tüübid,
mis selliseid väärtusi hoida suudavad, on aga täiesti erinevad. Seega täisautomaatse
tabelite tegemise puhul tuleb arvestada, et genereeritud kood ei pruugi kõige täpsemini
vajadusi rahuldada. Vähemalt mitte juhul kui kasutaja ise ei kirjelda endale sobilikke
tüübiteisendusi.
Et aga mitte vähendada Castori võimekust, siis olen tüüpide „tõlkimiseks“ appi
võtnud lihtsa XML-põhise tüüpide tõlkimise faili. Failis etc\datatypes.xml (vt Lisa 1) asub
kirjeldus sellest, millise Java tüübi peab Castor vastavusse seadma teatud SQL
tüüpidele ja vastupidi. Hetkel on seal enamlevinud tõlkimisvõimalused Java ja MySQL
vahel, vajadusel võib aga MySQL tüüpide asemel kasutusele võtta mõne teise
andmebaasisüsteemi tüübid või lisada juba kirjeldatud Umbrello tüüpidele mõne uue.
Ainsateks eeldusteks on kasutaja teadlikkus Castori võimetest (abiks URL
http://castor.exolab.org/types.html) ning kohustuslik „dbid“ tüübi kirjeldus.
22
4.5. Kontseptuaalsest mudelist Java objektideni
UML klassidiagrammi põhjal Java klasside tegemine on suhteliselt triviaalne
ülesanne. Sellist võimalust pakuvad mitmed modelleerimisvahendid. Klassidiagramm on
praktiliselt otse peale vaadates tõlgitav Java klassideks. Iga UML klass saab Java
klassiks, iga UML klassi atribuut Java atribuudiks, pärimisseose tõlgendus on samuti
väga lihtne ja ühene. Castori jaoks tuleb lisada dbid atribuut, ehk andmebaasi-
identifikaator. Ainus mittetriviaalsus on ehk assotsiatsioonide kajastamine. Kui üks klass
on seoses mingi teise klassiga, siis seose rollinime või teise klassi nime järgi saab
esimene neist vastavanimelise atribuudi. Atribuudi tüübiks saab Javas kas teine klass
või Java vektor (java.util.Vector). Vektorit kasutame, kui atribuut peab viitama mitmele
objektile, vektori elementideks on teise klassi tüüpi objektid.
Muidugi võiks UML seosetüüpe täpsemalt tõlgendada, näiteks võiks Java
klassidesse kirjutada vastavad meetodid, mis keelaks vektorisse lisada rohkem
elemente, kui seos seda ette näeb. Semestritöö praktilises osa ma sellist võimalust
(veel) siiski ei paku. Samuti kompositsiooniga:
Kompositsiooni väljendamiseks Javas saab võiks kasutada spetsiaalset
konstruktorit osa-poolsel klassil, konstruktor peaks nõudma argumendina ühte tervik-
poolset objekti, millega osa konstruktoris tervik seotakse. …Chapter (Book book) { book.addChapter(this);}Book book = new Book();Chapter c = new Chapter(book);
23
5. Objekt-relatsiooniline andmebaasisüsteem. CastorJDO
Castor kasutab XML-põhist andmeteisenduse faili, et aru saada milliseid objekte
lugeda/kirjutada millistest tabelitest ja milliseid klassi väljasid siduda milliste
veergudega. Objekti atribuudid ei pea olema üks-üheses vastavuses tabeli veergudega,
olenevalt vajadusest võib andmeteisenduse XML-is märkida ainult osad objekti
atribuudid; samuti ei pea kirjelduses kirja panema kõiki andmebaasitabeli veerge, OQL
päringute tegemisel Castor lihtsalt ei loe ega kirjuta XML-is kirjeldamata veerge.
OQL päringud. OQL on lühend sõnadest Object Query Language, ehk objektide
päringukeel. OQL sarnaneb mõneti SQL-iga, kuid tabelitest pärimise asemel päritakse
objektide hulgast. Castor töötleb OQL päringuid ja teisendab need SQL päringuteks.
Teisendades OQL päringust SQL päringuid kasutab Castor vastavat andmeteisenduse
kirjeldust. Castori OQL süntaks püüab järgida üldisi standardeid, peamiseks ODMG 3.0
OQL süntaks. Päris standardne Castori OQL siiski pole, kõiki OQL võimalusi pole
realiseeritud ja samas on kasutusel funktsionaalsust, mida ODMG standardis ette pole
nähtud. OQL näiteid:
„select i from Inimene i“„select i.eesnimi from Inimene i“„select i from Inimene i where i.vend.eesnimi=$1 and … order by…“„select i from inimene i where i.eesnimi=$1“,
kus $1 on parameeter mille saab Java koodis väärtustada näiteks nii:
bind(„Andres“);
OQL päringutega saab andmebaasist objekte Javasse lugeda, info
vastassuunaliseks liigutamiseks ehk Java objektide andmebaasi saamiseks on kaks
peamist võimlust:
1. Luua uus Java objekt, väärtustada tema kõik väljad ja kasutada Castori
database.create(Object o) meetodit. Objektile identifikaatori ehk
24
primaarvõtme genereerimiseks andmebaasis kasutab Castor andmeteisenduse
XML-is märgitud võtmegeneraatorit.
2. Pärast OQL päringu kasutamist muudame mõnda andmebaasist loetud objekti,
näiteks lisame temaga seoses olevatele objektide sekka mõne uue. Kui seda
teha ühe transaktsiooni jooksul ja kui Castori seadistustes on märgitud
database.setAutoStore(true), siis transaktsiooni lõppedes
(database.commit()) salvestab Castor kõik muudatused eelnevalt laetud
objektides, sealhulgas ka kõik seostega toimunud muudatused.
25
6. Põhjalikum näide
Olgu meil tarvis valmistada fotokonkursside andmebaas. Olgu meil mingi hulk
konkursse, igal konkursil on esindatud mingi hulk fotosid. Igale fotole peab saama
panna hindeid (ühest viieni) ja saama fotot kommenteerida. Üht fotot võib erinevatel
konkurssidel hinnata erinevalt. Iga foto kohta on teada tema autor. Järgnevalt näide
lihtsustatud klassidiagrammist, seejärel tulemused, mida andis klassidiagrammi
vastavale XMI failile rakendades käesoleva semestritöö käigus kirjutatud programm.
Lisatud ka näide andmebaasipäringu kirjutamise kohta Javas.
Mõned genereeritud failidest:
Fotograaf.java:import java.util.Vector;public class Fotograaf extends Inimene { public java.lang.Integer staaz; public java.lang.Integer telefon; public Vector foto;}
Foto.java:import java.util.Vector;public class Foto{ public java.lang.Integer DBID; public String pealkiri; public String jpeg; public Vector konkurss; public Vector hinnang; public Fotograaf fotograaf;}
26
Andmebaasitabelite kirjeldus
create_tables.sql:
CREATE TABLE foto ( dbid int(11) NOT NULL, pealkiri varchar(255), jpeg mediumblob, fotograaf_dbid int(11) NOT NULL, PRIMARY KEY (dbid));CREATE TABLE konkurss ( dbid int(11) NOT NULL, nimi varchar(255), algus timestamp(11), lopp timestamp(11), PRIMARY KEY (dbid));CREATE TABLE mn_foto_konkurss ( konkurss_dbid int(11) NOT NULL, foto_dbid int(11) NOT NULL INDEX(konkurss_dbid), INDEX(foto_dbid));CREATE TABLE hinnang ( dbid int(11) NOT NULL, hinne int(11), kommentaar varchar(255), foto_dbid int(11) NOT NULL, konkurss_dbid int(11) NOT NULL, zyrii_dbid int(11) NOT NULL, PRIMARY KEY (dbid));CREATE TABLE zyrii ( dbid int(11) NOT NULL, nimi varchar(255), PRIMARY KEY (dbid));CREATE TABLE fotograaf ( dbid int(11) NOT NULL, staaz int(11), telefon int(11), PRIMARY KEY (dbid));CREATE TABLE inimene ( dbid int(11) NOT NULL, eesnimi varchar(255), perenimi varchar(255), isikukood varchar(255), PRIMARY KEY (dbid));
27
Andmeteisenduse kirjeldus
mapping.xml:<?xml version="1.0" encoding="ISO-8859-1"?><mapping> <class name="Fotograaf" extends="Inimene" key-generator="MAX"> <map-to table="fotograaf"/> <field name="staaz" type="integer" direct="true"> <sql name="staaz" type="integer"/> </field> <field name="telefon" type="integer" direct="true"> <sql name="telefon" type="integer"/> </field> <field name="foto" type="Foto" collection="vector" direct="true"> <sql name="dbid" many-key="fotograaf_dbid" many-table="foto"/> </field> </class> <class name="Foto" identity="DBID" key-generator="MAX"> <map-to table="foto"/> <field name="DBID" type="integer" direct="true"> <sql name="dbid" type="integer"/> </field> <field name="pealkiri" type="string" direct="true"> <sql name="pealkiri" type="varchar"/> </field> <field name="jpeg" type="string" direct="true"> <sql name="jpeg" type="char"/> </field> <field name="konkurss" type="Konkurss" collection="vector" direct="true"> <sql name="konkurss_dbid" many-key="foto_dbid"
many-table="mn_foto_konkurss"/> </field> <field name="hinnang" type="Hinnang" collection="vector" direct="true"> <sql name="dbid" many-key="foto_dbid" many-table="hinnang"/> </field> <field name="fotograaf" type="Fotograaf" direct="true"> <sql name="fotograaf_dbid"/> </field> </class> ……… <class name="Hinnang" identity="DBID" key-generator="MAX"> <map-to table="hinnang"/> <field name="DBID" type="integer" direct="true"> <sql name="dbid" type="integer"/> </field> <field name="hinne" type="integer" direct="true"> <sql name="hinne" type="integer"/> </field> <field name="kommentaar" type="string" direct="true"> <sql name="kommentaar" type="varchar"/> </field> <field name="foto" type="Foto" direct="true"> <sql name="foto_dbid"/> </field> <field name="konkurss" type="Konkurss" direct="true"> <sql name="konkurss_dbid"/> </field> <field name="zyrii" type="Zyrii" direct="true"> <sql name="zyrii_dbid"/> </field> </class></mapping>
28
Näide päringute tegemise kohta
Example.java:import org.exolab.castor.jdo.*;
public class Example { private static JDO jdo; public static void main(String[] args) { try { jdo = new JDO(); //konfigureerime Castori jdo.setDatabaseName("example"); jdo.setConfiguration("database.xml"); Database db = jdo.getDatabase(); //alustame transaktsiooni db.begin(); //sõnastame OQL päringu: küsime kõik hinnangud OQLQuery oql=db.getOQLQuery("SELECT h FROM Hinnang h"); QueryResults results = oql.execute(); //väljastame iga fotole antud hinnangu kohta foto //pealkirja mida hinnati, antud hinde ja foto autori while ( results.hasMore() ) { Hinnang h = (Hinnang) results.next(); System.out.println("pealkiri: "+h.foto.pealkiri+ ", hinne: "+h.hinne+ ", autor: "+h.foto.fotograaf.perenimi); //teeme ka muudatusi objektides if (h.foto.fotograaf.eesnimi.equals("Andres")){ h.hinne = new Integer(5); } } //salvestame muudatused db.commit(); //sulgeme andmebaasiühenduse db.close(); } catch (Exception e){ e.printStackTrace(); } }}
Andmebaasiühenduse konfiguratsioon Castori jaoks
database.xml:<?xml version="1.0" encoding="UTF-8"?><database name="example" engine="mysql"> <driver class-name="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/example"> <param name="user" value="vilgota"/> <param name="password" value="vilgota"/> </driver> <mapping href="mapping.xml"/></database>
29
Kokkuvõte
Käesolevas semestritöös on käsitletud mudelil põhinevat objekt-orienteeritud
tarkvara loomise meetodit, tutvustatakse ka objekt-relatsiooniliste andmebaaside
kasutamist. Infosüsteemi andmete salvestamiseks on kasutatud ja kasutatakse ka
tulevikus relatsioonilisi andmebaase, käesoleva semestritöö tähelepanuväärsus seisneb
aga objekt-relatsioonilise andmeteisendaja Castor kasutamises objektivaate saamiseks
relatsioonilises andmebaas olevatele andmetele. Töö praktilise osana valmis programm,
mis modelleerimisvahendi Umbrello UML Modeller klassidiagrammi põhjal loob
automaatselt Java klassistruktuuri, tabelistruktuuri relatsioonilise andmebaasi jaoks ning
objekt-relatsioonilise teisenduskirjelduse Castori jaoks. Selliselt mudeli põhjal
genereeritud tarkvara loob head eeldused süsteemi kiireks muutmiseks, tarkvara
arendusprotsess ei takerdu süsteemi ümberkodeerimiseks kuluvatesse raskustesse.
Mudelil põhinev arhitektuur on tegelikult väga suure tähtsusega. Kui eeskujuks
võtta OMG MDA standard, siis võib valminud koodigeneraatori asemel valmistada palju
universaalsema programmi, mille sisendiks võib olla mistahes modelleerimisvahendi
klassidiagramm XMI formaadis, ning mis genereeriks objektide esitust mistahes viisil:
XML, Java, objektandmebaas, Castor, Hibernate, jne. Märksõnadeks mudelipõhise
arhitektuuri loomisel on XMI, PIM (Platform Independent Model), CWM (Common
Warehouse Meta-model), MOF (Meta-Object Facility).
30
Viited
[Amb03] Scott W. Amber (2003), Agile Database Techniques
(htttp://www.agiledata.org/essays/impedanceMismatch.html)
[Castor] ExoLab Groupi avatud lähtekoodil põhinev andmete sidumise
raamistik Java jaoks:
http://castor.exolab.org – viimati vaadatud 03.12.2003
[FS99] Martin Fowler, Kendall Scott (1999), UML Distilled: A Brief Guide to the
Standard Object Modeling Technique
[MDA] Model Driven Architecture, OMG standard,
http://www.omg.org/mda
[MVC01] E. Marcos, B. Vela ja J. M. Cavero (2001), Extending UML for Object-
Relational Database Design.
[ORMapping] Nimekiri objekt-relatsioonilistest andmeteisendajatest,
http://www.service-architecture.com/products/object-
relational_mapping.html – viimati vaadatud 06.12.2003
[ORVendors] Nimekiri objekt-relatsioonilistest andmebaasidest,
http://www.service-architecture.com/products/object-
relational_databases.html – viimati vaadatud 06.12.2003
[Umbrello] Umbrello UML Modeller, vabavaraline modelleerimistarkvara,
http://uml.sourceforge.net – viimati vaadatud 03.12.2003
31
Using UML conceptual models to persist Java objects inObject-Relational database.
Term paper
Andres Vilgota
Abstract
The most common way of designing complex object-oriented applications is using
Unified Modeling Language as the basis of a software development process. Complex
applications often need to provide persistence to its business objects, for which a
relational database can be used. Designing the connection between relational database
and an application may be quite a tedious task, but luckily object-relational databases
are gaining popularity in providing persistence to complex business objects. As the
mismatch between object-oriented paradigm and relational paradigm must still be
crossed, writing the application code by hand, defining the database schemas and
mapping objects to tables can be quite an effort.
In this paper I discuss the possibility of using so called Model Driven Architecture
to overcome the maintainability problems of this approach. Using Umbrello UML class
diagrams as the basis, just a little effort is needed to generate consistent Java code for
the business objects, table descriptions for the relational database and a mapping
description for object-relational mapping tool. As an example I developed a practical tool
which handles Umbrello UML class diagrams, utilizes the power of an object-relational
mapping tool called Castor and makes use of MySQL to generate persistence-capable
Java objects.
32
Lisad
Lisa 1. Näide tüübiteisenduste XML failist
(peatükk 4.4.2 juurde)
datatypes.xml:<?xml version="1.0" encoding="ISO-8859-1"?><dataTypes> <type UMLName="dbid"> <asJava>java.lang.Integer</asJava> <asCastorJava>integer</asCastorJava> <asSQL>int(11)</asSQL> <asCastorSQL>integer</asCastorSQL> </type> <type UMLName="string"> <asJava>String</asJava> <asCastorJava>string</asCastorJava> <asSQL>varchar(255)</asSQL> <asCastorSQL>varchar</asCastorSQL> </type> <type UMLName="bool"> <asJava>Boolean</asJava> <asCastorJava>java.lang.Boolean</asCastorJava> <asSQL>char(1)</asSQL> <asCastorSQL>char[YN]</asCastorSQL> </type> <type UMLName="integer"> <asJava>java.lang.Integer</asJava> <asCastorJava>integer</asCastorJava> <asSQL>int(11)</asSQL> <asCastorSQL>integer</asCastorSQL> </type> <type UMLName="date"> <asJava>java.util.Date</asJava> <asCastorJava>date</asCastorJava> <asSQL>timestamp(11)</asSQL> <asCastorSQL>timestamp</asCastorSQL> </type> <type UMLName="blob"> <asJava>String</asJava> <asCastorJava>string</asCastorJava> <asSQL>mediumblob</asSQL> <asCastorSQL>char</asCastorSQL> </type></dataTypes>
33
Lisa 2. Esialgse XMI faili lihtsustamiseks mõeldud XSL skript
xmitransformer.xsl:
<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"version="1.0"><xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/><xsl:strip-space elements="*"/><xsl:template match="umlobjects"> <UMLObjects> <xsl:for-each select="*"> <xsl:call-template name="recurseCopy"/> </xsl:for-each> </UMLObjects></xsl:template><xsl:template match="XMI.header"></xsl:template><xsl:template name="recurseCopy"> <xsl:choose> <xsl:when test="local-name()=''"> <xsl:copy/> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="local-name()='Class' or local-name()='Attribute' or local-name()='Operation'or local-name()='Parameter'or local-name()='Association'"> <xsl:element name="UML{local-name()}" namespace=""> <xsl:for-each select="@*"> <xsl:attribute name="{local-name()}"> <xsl:value-of select="current()"/> </xsl:attribute> </xsl:for-each> <xsl:for-each select="node()"> <xsl:call-template name="recurseCopy"/> </xsl:for-each> </xsl:element> </xsl:when> </xsl:choose> </xsl:otherwise> </xsl:choose></xsl:template></xsl:stylesheet>
34
Lisa 3. Failide loetelu
(failid allalaetavad http://www.egeen.ee/u/vilgota/)
etc/datatypes.xmletc/mapper.database.xsdetc/mapper.datatypes.xsdetc/mapper.propertiesetc/mapper.xmireader.xsdetc/mapping.xmletc/xmitransformer.xslmapper/AssociationHandler.javamapper/MappingGenerator.javamapper/MultiReader.javamapper/MyAssociation.javamapper/MyAttribute.javamapper/MyClass.javamapper/MyDiagram.javamapper/SQLAttribute.javamapper/SQLColumn.javamapper/SQLTable.javamapper/SQLTables.javamapper/TypeTranslator.javamapper/XMITransformer.javamapper/database/Database.javamapper/database/Driver.javamapper/database/Mapping.javamapper/database/Param.javamapper/datatypes/DataTypes.javamapper/datatypes/Type.javamapper/xmireader/UMLAssociation.javamapper/xmireader/UMLAttribute.javamapper/xmireader/UMLClass.javamapper/xmireader/UMLObjects.javamapper/xmireader/UMLOperation.javamapper/xmireader/UMLParameter.java
35