Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: Zend: ORM:n implementointi

Triton [08.05.2012 14:52:03]

#

Olen tässä useita päiviä pyöritellyt mielessäni, että miten Zend Frameworkissa olisi parasta implementoida ORM eli Object-Relation Mapping. Zend ei suoranaisesti itse ota kantaa siihen, että miten tämä tulisi toteuttaa...
Oma ongelmani on se, että haluan toteuttaa yleensäkin kaiken, mikä liittyy sovelluksen rakenteeseen, mahdollisimman hyvin ja loogisesti ja nyt en pääse ORM:n kanssa sellaiselle loogisuuden tasolle kuin haluaisin.

Ensinnäkin jokaisessa ohjelmassa on tietty määrä erilaisia olioita, jotka mallintavat käsiteltävän kontekstin mukaisia käsitteitä, joita itse kutsun entiteeteiksi tai malleiksi (MVC:n mukaan). Nämä entiteetit toteuttavat ohjelman ns. bisneslogiikan. No koska tietoa on yleensäkin pystyttävä tallentamaan johonkin, niin tällöin kuvioon astuu relaatiotietokannat. Loogistahan on, että esim. käyttäjät-taulun yksittäistä tietuetta vastaa ajonaikaisesti ohjelmassa yksittäinen käyttäjä-olio, jonka attribuutit vastaavat kyseisen tietueen sarakkeita. Ongelmaksi kuitenkin muodostuu se, että mikä on kaikkein paras tapa konverttaa näitä tietokannan tietueita olioiksi ja päinvastoin. Aluksi ajattelin, että teen jokaista entiteetti-oliota vastaavan datamapperin, joka siis ottaa vastaa yksittäisen olion ja tuottaa siitä tarvittavat insert- tai update- lauseet tai vastaavasti suorittaa select-kyselyn ja pakkaa vastauksen entiteetti-olioksi, mutta sitten ongelmaksi muodostui olioiden sekä vastaavasti taulujen väliset riippuvuudet. Ei ole missään tapauksessa fiksua, että esim. käyttäjä-mapper palauttaisi sellaista käyttäjä-oliota, jonka sisäänsä kapseloima taulukkorakenne sisältäisi esim. tuon käyttäjän omistamat viesti-oliot, koska ennemmin tai myöhemmin loppuisi muisti kesken. Fiksua on siis, että käyttäjä-olio hakee nuo viesti-oliot tietokannasta vain siinä tapauksessa, että niitä eksipliittisesti pyydetään siltä. Kiinnostaisikin tietää, että onko loogista, että käyttäjä-oliolla voisi olla viite esim. viesti-mapperiin? Tällöin viestit pystyttäisiin hakemaan tarvittaessa sitä kautta. Pragmaattisuuden näkökulmasta siinä on järkeä, mutta onko logiikan? Monesti ORM-toteutetaan nk. Active Record -suunnittelumallin avulla, mutta mielestäni tässä suunnittelumallissa ei ole järkeä, koska eihän entiteetti voi olla millään tavalla yhteydessä tietokantaan niin suoraan.

Tiivistettynä: Haen siis jonkinlaista järkevää tapaa toteuttaa ORM-rakenne Zendissä.

tsuriga [08.05.2012 15:28:40]

#

Voit käyttää valmista ORM-palikkaa, esim. Doctrine 2:sta, joka tuntuisi lyhyen haeskelun perusteella olevan suositumpi kuin toinen vaihtoehto Propel. Doctrine 2 toimii datamapperimaisesti (1 ilmeisesti Active Record -tyyppisesti?).

Keskustelua Stack Overflow:ssa + muutamia nopeasti haettuja tutoriaaleja

Tukki [08.05.2012 15:29:33]

#

Suosittelen käyttämään valmista, jollen välttämättä halua harjoitella juuri tätä puolta ohjelmoinnissa tai jos sinulla ei ole hyvää perustelua miksi kaikki valmiit ovat epäsopivia. PHP:lle on mm. Active Record-toteutus Propel ja minulle vähän tuntemattomampi Doctrine. ORM on aika monimutkainen osa sovellusta enkä itse slkaisi sitä tekemään jos valmiilla pärjää.

Taulujen välisten riippuvuuksien käsittely on yksi hankala kohta ormien kanssa. Niinkuin sanoit, jos kaikki haetaan kerralla, usein haetaan turhaa dataa ja olioita ja muistinkulutus kasvaa turhaa. Toisaalta jos riippuvuuksia ei haeta, usein joudutaan tekemään useampia kantakyselyitä kuin mitkä olisi optimaalista. Jos esimerkissäsi haluat näyttää vaikkapa listan käyttäjistä ja heidän kirjoittaman viestien määrän, joutuisit tekemään n+1 kyselyä kun yhdelläkin saa tarvittavat tiedot.

Propelissa tuota ongelmaa käsitellään mm. niin että oletusarvoisesti riippuvuuksia ei haeta ellei erikseen pyydetä, mutta joka kyselyn yhteydessä voit sanoa minkä taulujen kanssa haluat haun joinata, jolloin ne lisätään hakuun ja vastaavat oliotkin luodaan valmiiksi. Toki voit myös tehdä täysin oman sql:n ja hyödyntää silti Propelia olioiden populoimiseen.

Toinen monimutkainen kohta on perinnän toteuttaminen relaatiokannassa. Propel tarjoaa tähän ainakin paria eri vaihtoehtoa joista voi valita omaan tilanteeseen sopivan. Toinen muistaakseni tallentaa kaikki oliot samaan tauluun ja toinen käyttää periville luokille omia taulujaan.

Tiivistettynä: Käytä Propelia. Jos se ei tunnu hyvältä, tutustu Doctrineen tai etsi muita valmiita.

Triton [08.05.2012 16:25:30]

#

Kiitos vastauksista. Pää vaan hajoaa, kun yrittää tätä koko ORM:ää hahmottaa. Nuo Active Record -tyyppiset ratkaisut eivät vain tunnu tarpeeksi loogisilta, mutta nyt alkaa näyttää siltä, että pakko on vain ottaa joku valmis palikka käyttöön, vaikkakin sydän vuotaa verta :D. Miksei voisi olla olemassa kunnon olio-tietokantoja, jonne voisi tallentaa olioita ja hakea olioita, niin ei tarvitsisi koko ORM:ää olla välissä.

The Alchemist [08.05.2012 17:00:40]

#

NoSQL-tietokannat
MongoDB

Itse olen tuota Mongoa käyttänyt yhdessä Node.js-sovelluksessani. Kyse ei sinällään ole juuri object oriented -tietokannasta mutta jostain sen suuntaisesta

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta