Spring Framework / 10. časť

V mi­nu­lej čas­ti sme si pred­sta­vi­li pr­vé tri ty­py vä­zieb me­dzi en­ti­ta­mi - 1:1, 1:N a N:1. Tie­to väz­by sa vy­zna­ču­jú aj tým, že je mož­né ich reali­zo­vať aj bez pou­ži­tia aso­cia­tív­nej ta­buľ­ky. Po­kiaľ to vý­ni­moč­ná si­tuácia vy­ža­du­je, je pou­ži­tie aso­cia­tív­nej ta­buľ­ky mož­né, ale väč­ši­nou sa jed­ná o zby­toč­nú kom­pli­ká­ciu. Nao­pak pre pos­led­ný typ vzťa­hu, M:N, je aso­cia­tív­na ta­buľ­ka nut­nos­ťou.

Re­lá­cia M:N

Ako ste už asi vy­tu­ši­li, vzťah ty­pu M:N (ale­bo tiež Ma­ny-To-Ma­ny) je viac­ná­sob­ná re­lá­cia me­dzi en­ti­ta­mi, kde in­štan­cie en­ti­ty na ľa­vej stra­ne vzťa­hu mô­žu byť zdie­ľa­né me­dzi via­ce­rý­mi in­štan­cia­mi en­ti­ty na pra­vej stra­ne vzťa­hu a zá­ro­veň nao­pak. Ten­to vzťah by sme moh­li mo­de­lo­vať na prík­la­de tried Di­rec­tor a Mo­vie z mi­nu­lých čas­tí se­riá­lu, ak by sme pri­pus­ti­li mož­nosť, že je­den film mô­že mať via­ce­rých re­ži­sé­rov (a sa­moz­rej­me je­den re­ži­sér mô­že re­ží­ro­vať viac fil­mov). Na úrov­ni da­ta­bá­zo­vých re­lač­ných ta­bu­liek by to moh­lo vy­ze­rať tak, ako uka­zu­jú ta­buľ­ky 1 až 3.

DI­REC­TOR

ID

NA­ME

1

Ja­kub Ju­ra­jis­ko

2

Al­ly Wooden

3

Ta­ran­tin Quen­ti­no

Tab. 1: Ta­buľ­ka en­ti­ty Di­rec­tor

 

DI­REC­TOR_MO­VIE

ID_DI­REC­TOR

ID_MO­VIE

1

1

2

1

1

2

1

3

3

3

2

4

3

4

Tab. 2: Aso­cia­tív­na ta­buľ­ka

 

MO­VIE

ID

NA­ME

1

Good Mo­vie

2

Ve­ry Good Mo­vie

3

Excellent Mo­vie

4

The Best Mo­vie

Tab. 3: Ta­buľ­ka en­ti­ty Mo­vie

 Ako vi­dí­me, v tom­to prík­la­de má­me vy­tvo­re­né tri in­štan­cie en­ti­ty Di­rec­tor a šty­ri in­štan­cie en­ti­ty Mo­vie. Pod­ľa vzťa­hov na­de­fi­no­va­ných v aso­cia­tív­nej ta­buľ­ke má dru­hý film jed­né­ho re­ži­sé­ra, os­tat­né ma­jú vždy dvoch. Ale­bo z opač­né­ho poh­ľa­du, pr­vý re­ži­sér sa po­die­ľal na troch fil­moch, os­tat­ní dva­ja ma­jú na kon­te kaž­dý dva. Na úrov­ni re­lač­nej da­ta­bá­zy je tak­to de­fi­no­va­ný vzťah vždy oboj­smer­ný - k da­nej in­štan­cii na kto­rej­koľ­vek stra­ne re­lá­cie je mož­né zís­kať aso­cio­va­né in­štan­cie na opač­nej stra­ne vzťa­hu.

Na ap­li­kač­nej úrov­ni bu­de po­tom nut­né up­ra­viť en­ti­tu Di­rec­tor nas­le­dov­ne:

@En­ti­ty

@Tab­le(na­me="di­rec­tor")

class Di­rec­tor im­ple­ments Se­ria­li­zab­le {

...

@Ma­ny­To­Ma­ny

@Join­Tab­le(

      na­me="di­rec­tor_mo­vie",

      join­Co­lumns={@Join­Co­lumn(na­me="id_di­rec­tor",

                  re­fe­ren­ced­Co­lum­nNa­me="id")},

      in­ver­se­Join­Co­lumns={@Join­Co­lumn(na­me="id_mo­vie",

                  re­fe­ren­ced­Co­lum­nNa­me="id")})

pri­va­te List<Mo­vie> mo­vies;

...

De­fi­no­va­nie aso­cia­tív­nej ta­buľ­ky je po­mer­ne jed­no­du­ché - ako vi­dí­me, slú­ži k to­mu ano­tá­cia @Join­Tab­le. Po­mo­cou at­ri­bú­tu na­me špe­ci­fi­ku­je­me me­no aso­cia­tív­nej ta­buľ­ky a nás­led­ne po­mo­cou at­ri­bú­tov join­Co­lumns a in­ver­se­Join­Co­lumns pre­po­je­nie me­dzi aso­cia­tív­nou ta­buľ­kou a hlav­ný­mi ta­buľ­ka­mi. Tie­to at­ri­bú­ty sú de­fi­no­va­né po­mo­cou ano­tá­cií @Join­Co­lumn, s kto­rý­mi sme sa stret­li už v mi­nu­lej čas­ti pri roz­prá­va­ní o vzťa­hu 1:N. Ten­to fakt nie je ná­hod­ný, pre­to­že vzťah me­dzi kaž­dou hlav­nou ta­buľ­kou a aso­cia­tív­nou ta­buľ­kou je vlas­tne vzťa­hom 1:N.

Nes­mie­me tiež za­bud­núť na ano­tá­ciu @Ma­ny­To­Ma­ny, kto­rá ozna­ču­je at­ri­bút reali­zu­jú­ci re­lá­ciu M:N v en­ti­te Di­rec­tor.

Tak­to de­fi­no­va­ný vzťah je na ap­li­kač­nej úrov­ni jed­nos­mer­ný, tak­že in­štan­ciám trie­dy Di­rec­tor umož­ňu­je zís­kať od­ka­zy na všet­ky aso­cio­va­né in­štan­cie en­ti­ty Mo­vie, av­šak opač­ným sme­rom to mož­né nie je. Ak by sme chce­li vzťah reali­zo­vať ako oboj­smer­ný, mu­sí­me eš­te up­ra­viť trie­du Mo­vie:

@En­ti­ty

@Tab­le(na­me="mo­vie")

class Mo­vie im­ple­ments Se­ria­li­zab­le {   

...  

@Ma­ny­To­Ma­ny(map­ped­By="mo­vies")

pri­va­te List<Di­rec­tor> di­rec­tors;

...

Ako vi­dieť, v tom­to prí­pa­de sta­čí len zno­vu vy­užiť ano­tá­ciu @Ma­ny­To­Ma­ny a pri­dať at­ri­bút map­ped­By, kto­rým špe­ci­fi­ku­je­me me­no at­ri­bú­tu v ma­po­va­nej trie­de - tak­že v tom­to prí­pa­de vlas­tne ho­vo­rí­me, že ide o in­verz­ný smer k re­lá­cii de­fi­no­va­nej at­ri­bú­tom mo­vies v trie­de Di­rec­tor. Ten­to prís­tup pre de­fi­no­va­nie opač­né­ho sme­ru re­lá­cie po­mo­cou at­ri­bú­tu map­ped­By je po­vin­ný - po­kiaľ by sme ho nao­pak na­de­fi­no­va­li po­mo­cou ano­tá­cie @Join­Tab­le ako v prí­pa­de trie­dy Di­rec­tor, bo­li by vý­sled­kom zdvo­je­né zá­zna­my v aso­cia­tív­nej ta­buľ­ke di­rec­tor_mo­vie. Pre­to je dô­le­ži­té, aby bol vzťah M:N de­fi­no­va­ný na ap­li­kač­nej úrov­ni len v jed­nej z en­tít, za­tiaľ čo os­tat­né en­ti­ty sa mu­sia na tú­to de­fi­ní­ciu len od­ka­zo­vať, v prí­pa­de pot­re­by.

La­zy fet­ching

Kaž­dá z ano­tá­cií pre de­fi­no­va­nie re­lá­cií me­dzi en­ti­ta­mi (@One­ToO­ne, @One­To­Ma­ny, @Ma­ny­ToO­ne a @Ma­ny­To­Ma­ny) umož­ňu­je špe­ci­fi­ká­ciu at­ri­bú­tu fetch. Ten­to at­ri­bút inštruu­je ORM fra­mework, akým spô­so­bom ma­jú byť ini­cia­li­zo­va­né in­štan­cie aso­cio­va­nej en­ti­ty, resp. pres­nej­šie od­ka­zy na tie­to in­štan­cie. K dis­po­zí­cii sú dve mož­nos­ti (obe de­fi­no­va­né vo vy­me­no­va­nom ty­pe FetchTy­pe):

1) EAGER - im­pli­cit­ná hod­no­ta, aso­cio­va­né in­štan­cie bu­dú na­čí­ta­né spo­lu s hlav­nou in­štan­ciou. Ak te­da po­mo­cou ORM fra­mewor­ku na­čí­ta­me kon­krét­nu in­štan­ciu en­ti­ty Di­rec­tor, bu­de ini­cia­li­zo­va­né i po­le mo­vies všet­ký­mi aso­cio­va­ný­mi in­štan­cia­mi en­ti­ty Mo­vie. Sa­moz­rej­me, to­to sprá­va­nie mô­že mať v prí­pa­de zlo­ži­tých dá­to­vých mo­de­lov kas­ká­do­vý efekt, keď na­čí­ta­nie jed­nej in­štan­cie (resp. jed­né­ho riad­ku) z da­ta­bá­zy mô­že vy­vo­lať na­čí­ta­nie ob­rov­ské­ho množ­stva ďal­ších úda­jov z aso­cio­va­ných ta­bu­liek (a re­kur­zív­ne opäť ďal­ších riad­kov z ich aso­cio­va­ných ta­bu­liek). V prí­pa­de, že je to­to sprá­va­nie ne­žia­du­ce, je k dis­po­zí­cii dru­hý typ na­čí­ta­nia aso­cio­va­ných in­štan­cií - LA­ZY.

2) LA­ZY - tzv. le­ni­vá ini­cia­li­zá­cia, kde aso­cio­va­né in­štan­cie sú na­čí­ta­né až v mo­men­te, keď sa k nim ap­li­ká­cia po­kú­si pris­tú­piť. Ten­to prís­tup mô­že zlep­šiť vý­kon ap­li­ká­cie v prí­pa­de, že dá­to­vý mo­del je zlo­ži­tý a ap­li­ká­cia pot­re­bu­je vždy len časť úda­jov, ale nik­dy nie všet­ky (nap­rík­lad  pre up­ra­ve­nie hod­no­ty jed­né­ho at­ri­bú­tu nie je nut­né na­čí­ta­vať ce­lý strom aso­cio­va­ných in­štan­cií). Ten­to prís­tup má však i svo­je ne­vý­ho­dy, nap­rík­lad pri ňom mô­že do­chá­dzať k ne­kon­zis­ten­cii sta­vu dát v ap­li­ká­cii - stav aso­cio­va­ných in­štan­cií v do­be ich na­čí­ta­nia sa ne­mu­sí zho­do­vať s ich sta­vom v mo­men­te, keď bo­la na­čí­ta­ná hlav­ná in­štan­cia.

Po­kiaľ by sme chce­li vy­užiť vý­ho­dy le­ni­vej ini­cia­li­zá­cie nap­rík­lad v prí­pa­de trie­dy Di­rec­tor a aso­cio­va­nej trie­dy Mo­vie, sta­či­lo by zme­niť de­fi­ní­ciu at­ri­bú­tu mo­vies v trie­de Di­rec­tor nas­le­dov­ne:

 @Ma­ny­To­Ma­ny(fetch=FetchTy­pe.LA­ZY)

@Join­Tab­le(...)

pri­va­te List<Mo­vie> mo­vies;

Tak­to za­bez­pe­čí­me, že v prí­pa­de, že bu­de­me pra­co­vať s in­štan­cia­mi trie­dy Di­rec­tor, ne­bu­dú pri jej na­čí­ta­ní z da­ta­bá­zy na­čí­ta­né auto­ma­tic­ky aj aso­cio­va­né fil­my (in­štan­cie trie­dy Mo­vie). K na­čí­ta­niu fil­mov da­né­ho re­ži­sé­ra dôj­de až v mo­men­te, keď to bu­de ap­li­ká­cia pot­re­bo­vať - te­da pri po­ku­se o prís­tup ku ko­lek­cii mo­vies.




Ohodnoťte článok:
   
 

24 hodín

týždeň

mesiac

Najnovšie články

Spring Fra­mework / 10. časť
V minulej časti sme si predstavili prvé tri typy väzieb medzi entitami - 1:1, 1:N a N:1. Tieto väzby sa vyznačujú aj tým, že je možné ich realizovať aj bez použitia asociatívnej tabuľky. čítať »
 
Prog­ra­mu­je­me GPU / 16. časť
Touto časťou seriálu začneme opisovať algoritmy shaderov, ktoré sme navrhli v predošlom období. Prakticky sa vrátime k obsahu 6. časti seriálu, v ktorej sme vám predstavili súborovú štruktúru prvej verzie vzorovej aplikácie. Tentoraz sa však nebudeme venovať štruktúre, ale obsahu súborov. čítať »
 
Zdie­ľa­nie zdro­jov me­dzi OS Win­dows a OS Li­nux / 5. časť
Tento článok veľmi úzko súvisí s obsahom predošlej časti seriálu. Tentoraz sa však zameriame na vzájomné sprístupnenie zložiek medzi dvoma PC s OS Linux. čítať »
 
Li­nux prak­tic­ky ako server / Do­main Na­me Sys­tem – ty­py DNS server­ov
V predchádzajúcej časti sme vysvetlili podstatu systému DNS, povedali sme si niečo z histórie o potrebe a vzniku DNS. Zmienili sme sa aj o tom, čo sú top level domény a aký je rozdiel medzi logickou a fyzickou štruktúrou. čítať »
 
Preh­ľad bez­plat­ných na­vi­gá­cií pre An­droid a iOS
Z hľadiska pomeru cena/výkon pravdepodobne najlepšia aplikácia z kategórie bezplatných riešení, ale dostupná je iba pre zariadenia s operačným systémom Android. čítať »
 
Kniž­né no­vin­ky
Chcete pochopiť, aké tajomstvo stojí za úspechom spoločnosti Google? Skutočne len niekoľko málo spoločností na svete je obdivované ako Google, ktorý premenil internet a stal sa neoddeliteľnou súčasťou našich životov. čítať »
 
Vi­sual Stu­dio 2012
História tvorby vývojárskych nástrojov siaha až do začiatku histórie Microsoftu, konkrétne do roku 1975, keď bol vytvorený programovací jazyk Basic pre Altair. Odvtedy uplynuli takmer štyri desaťročia a Microsoft približne s dvojročnou periodicitou dodáva vývojárom nové verzie nástrojov. čítať »
 
Vý­voj pre Win­dows 8: Ozná­me­nia
Tento seriál sme v snahe o maximálnu aktuálnosť úmyselne načasovali do etapy testovania Preview verzií Windows 8, takže niektoré veci sa dynamicky vyvíjajú. čítať »
 
 
 
  Zdieľaj cez Facebook Zdieľaj cez Google+ Zdieľaj cez Twitter Zdieľaj cez LinkedIn Správy z RSS Správy na smartfóne Správy cez newsletter