Ohjelmistojen mallintamisen ja tietokantojen perusteiden yhteys Tällä kurssilla on tutustuttu ohjelmistojen mallintamiseen oliomenetelmiä ja UML:ää käyttäen Samaan aikaan järjestetyllä kurssilla on käsitelty relaatiotietokantojen ja tietosisällön mallintamista yhtenä työkaluna on ollut UML:n luokkakaavio Oliomallinnuksessa mallinnetaan ohjelmistojen toimintaa useammalta abstraktiotasolta Relaatiomallinnuksessa taas mallinnetaan pysyväisluonteista (tallennettavaa) dataa Lähes kaikki ohjelmistot käyttävät pysyväisluonteista dataa
Tiedon mallintaminen relaatiotietokannassa Järjestelmän tietosisältöä mallinnetaan useammalla abstraktiotasolla Kohdealueen tietosisältöä mallinnettaessa halutaan Luokkakaavio (käsitetaso) Tietokantakaavio (looginen taso) Ja mahdollisesti fyysisen tason kaavioita ei käsitelty tietokantojen perusteissa Järjestelmän suorituskyky oleellista, tarkoituksena on löytää tehokas tallennustapa Tietokannanhallintajärjestelmä käsittelee miljoonia tietueita
Oliomallinnus ja relaatiotietokanta UML-luokkakaaviossa mallinnetaan luokkien rakennetta. Oliot ovat luokkien ilmentymiä. Relaatiotietokannassa yksi olio vastaa yhtä riviä tietokantataulussa. Tällä hetkellä vallitsevissa olio-ohjelmointikielissä ei ole vastaavaa hakutoiminallisuutta kuin relaatiotietokannoissa Relaatiotietokannat mahdollistavat myös ohjelmointikieliriippumattoman näkymän tallennettuun tietoon Olio-ja relaatiomallien yhteensovittamiseksi käytetään oliorelaatiokuvausta (object-to-relational mapping, ORM)
Tietokantataulu Taulun nimi ROOLI ID NIMI sarakkeet 1 Tuottaja yksittäinen arvo 2 Näyttelijä rivejä 3 Ohjaaja Ylläolevaa taulua vastaava luokka: public class Rooli { private String nimi;... } Viitteen id kanssa: public class Rooli { private int id; private String nimi;... }
Olioiden esittäminen relaatiokannassa Olioiden tallentaminen tietokantaan on usein suoraviivaista public class Huoltohenkilo { private String nimi; private String puhelinnumero; private List<Huoltotapahtuma> huoltotapahtumat;... } public class Huoltotapahtuma { private String kuvaus; private Huoltohenkilo henkilo;... }
Olioiden esittäminen relaatiokannassa Lisätään luokkakaavioon avaimet (id-kentät) public class Huoltohenkilo { private int id; private String nimi; private String puhelinnumero; private List<Huoltotapahtuma> huoltotapahtumat;... } public class Huoltotapahtuma { private int id; private String kuvaus; private Huoltohenkilo henkilo;... }
Olioiden esittäminen relaatiokannassa Luodaan tietokantataulut SQL-create komennoilla: CREATE TABLE Huoltohenkilo ( id int, nimi text, puhelinnumero text, constraint huoltohenkilo_pk primary key (id)) CREATE TABLE Huoltotapahtuma ( id int, kuvaus text, constraint huoltotapahtuma_pk primary key (id), constraint huoltohenkilo_fk foreign key (huoltohenkilo_id) references Huoltohenkilo(id)) Kun olio tallennetaan tietokantaan, siitä luodaan rivi (tai päivitetään siihen liittyvää jo olemassaolevaa riviä) Kun olio ladataan tietokannasta, ladataan olio tietyn id:n (tai hakuehtojen) perusteella
Olioiden esittäminen relaatiokannassa Entä jos huoltohenkilölle liitetään osoite? Yksi tapa käyttää kompositiota. Miten relaatiomallissa? Onko Osoite-luokan kentät (ei näytetty) Asiakas-taulun sarakkeita? Luodaanko Osoite-luokalle oma erillinen taulu? Olio- ja relaatiomallin yhteensovittaminen ei ole aina helppoa.
Yhteensovittamisen ongelmia Olio- ja relaatiomallien yhteensovittamisessa näkyviä ongelmia syntyy esim. seuraavista: Mallinnuksen tarkkuustaso Luokkahierarkian tallennus Olioiden identiteetit Yhteyksien tallentaminen Yhteyksien navigoituminen Joidenkin arvioiden mukaan jopa 30% vanhempien oliojärjestelmien koodiriveistä on toisteista olio- ja relaatiomuunnosten toteuttamista.
Yhteensovittamisen ongelmia Esim viidensissä laskuharjoituksissa (Java-puolella) nähty muunnos Viesti-olioiksi: public List<Viesti> haeviestit() throws SQLException { List<Viesti> viestit = new ArrayList(); Connection yhteys = luoyhteys(); Statement kysely = yhteys.createstatement(); ResultSet tulosjoukko = kysely.executequery("select * from Viesti"); while (tulosjoukko.next()) { int id = tulosjoukko.getint("id"); int kayttajaid = tulosjoukko.getint("kayttaja_id"); Date kirjoitusaika = tulosjoukko.getdate("kirjoitusaika"); String teksti = tulosjoukko.getstring("teksti"); } Viesti v = new Viesti(id, kayttajaid, kirjoitusaika, teksti); viestit.add(v); } yhteys.close(); return viestit;
Yhteensovittamisen ongelmia Perinnälle ei ole suoraa vastetta relaatiomallissa. Kukin aliluokka määrittelee oman tietosisältönsä Kullakin oliolla on luokka Taulujen viiteavaimet voivat osoittaa vain yhteen viitattuun tauluun
Identiteetti Huoltohenkilön identifioivaksi kentäksi määriteltiin uusi kenttä id Javassa olioita voidaan tunnistaa viitesamuuden ja identiteettisamuuden kannalta Viitesamuus: olio1 == olio2 Identiteettisamuus: olio1.equals(olio2) Tietokannan avainkenttä tuo kolmannen samuuden käsitteen Esimerkiksi tietojen muokkaustilanteessa järjestelmässä voi olla olioita, jotka viite- ja identiteettitasolla ovat eriäviä, mutta tietokannan kannalta samoja
Yhteyksien tallentaminen UML:ssä navigoituvuussääntöjä merkitään nuolen avulla. Nuoli vastaa olion viitettä Olioviite viittaa aina yhteen suuntaan Molempiin suuntiin navigoitavat yhteydet toteutetaan kahtena olioviitteenä Relaatiokannassa viiteavain viittaa pääavaimeen
Navigoiminen olioverkoissa Olioista koostuville ohjelmille on luontaista käsitellä olioverkkoja ja siirtää palvelu osaolioille Palveluun osallistuvien olioiden tunnistaminen on vaikeaa etukäteen oliomallinnus auttaa Olioiden hakeminen tietokannasta ei ole aina tehokasta: Kunkin olion noutaminen tietokannasta siinä vaiheessa, kun olioon liittyviä tietoja tarvitaan, on tehotonta n+1 kyselyn ongelma
ORM Olio- ja relaatiomallien välisten yhteyksien kuvaamiseen käytetään usein erillistä työkalua tai sovelluskehystä ORM-kuvaus määrittelee miten oliomalli esitetään relaatiotietokannassa ORM-työkalu tarjoaa rajapinnat olioiden tietokannasta lataamiseksi ja tallentamiseksi Javassa standardi Java Persistence API
ORM:n ratkaisema ongelmakenttä ORM-työkalut pyrkivät vastaamaan seuraaviin mm. kysymyksiin: Minkälainen rakenne tallennettavilla luokilla tulee olla Miten O/R kuvaukset esitetään Miten periytymisrakenteet tallennetaan Olioidentiteettiin liittyvät ongelmat Miten sovelluslogiikka toimii tallennuslogiikan kanssa kerrostettu arkkitehtuuri! Miten tallennettavat oliot elävät Miten olioita noudetaan tietokannasta Miten olioverkkoja noudetaan tehokkaasti
JPA Java Persistence API Pysyväisolioiden tallentamiseen käytettävä rajapinta Nykyään käytössä toinen versio, JPA2 Demo.