Sziasztok!
Van egy problémám, amit már kellően agyhalott állapotomban nem tudtam megoldani. Adott egy LDAP könyvtár, benne userek és azoknak jogai. Ezt szerettem volna leképezni domain objektumokra. (A domain egyik felét Hibernate terelgeti, a másikat pedig a spring-ldap project LdapTemplate osztálya.) A userek és jogaik között az alábbi asszociáció áll fent:
public class User
{
[...]
private Set<Role> roles;
[...]
}
public class Role
{
[...]
private Set<User> members;
[...]
}
Mint látható ez egy many-to-many bidirectional kapcsolat. Az LdapTemplate használata során mappelnem kell az LDAP struktúrából az entitásokat, így amikor usereket kérdezek le, akkor kitöltöm a roles setet a user memberOf attribútuma alapján. A probléma ezzel az, hogy ilyenkor létre kell hoznom a Role példányokat is, amelyek ismét csak hivatkoznak a Userekre. Ebből ebben a formában egy végtelen ciklus és egy StackOverflowError lesz. A Hibernate ezt a mappedBy attribútum bevezetésével oldja meg, amely kijelöli, hogy melyik a reláció "owning" oldala és így okosan tudja, hogy mit kell csinálni. Az LdapTemplate azonban nem ilyen szofisztikált. Erre keresek valamilyen elegáns, szép megoldást. Lazy loadingos proxyt nem nagyon szeretnék bevezetni a Setekre, mert igazából semmi időm nincs rá és tegnapra kellett volna az egész. :) Mindkét oldalról látnom kell az asszociációt, így az sem jó, hogy unidirectional jellegűre veszem.
A válaszokat előre is köszi,
M.
- 1108 megtekintés
Hozzászólások
Én ugyan JAvahoz nem értek, de a "C++ kódolási szabályok" c. alapműben azt írják, hogy kerülni kell az ilyen egymásra hivatkozó ojjektumokat. Aztán abból még nem volt baj, ha betartották az ott írtakat. :)
A Role classnak miért kell a members field? Feltétlen szükséges?
Mondom, Java-t épphogy tanulgatom (Hello Worldnél járok), de OOP az OOP.... :)
- A hozzászóláshoz be kell jelentkezni
Javaban ez viszonylag megszokott, főleg, hogyha valamilyen perzisztencia frameworkot használsz, ami elintézi neked, hogy ne lehessen ebből galiba. Lényegében generál egy proxyt, ami csak akkor tölti be az asszociáció tényleges tartalmát, ha valóban szükséged van rá és el akarod azt érni.
- A hozzászóláshoz be kell jelentkezni
Köszönöm a felvilágosítást, elnézést, hogy tudatlanul beledumáltam, nem tudtam, hogy Javaban ennyire más az OOP szemlélet.
- A hozzászóláshoz be kell jelentkezni
Pont errol van szo. Nem mas az oop szemlelet, oop ertelemben nincs keresztreferencia. Van egy fuggveny, ami kepes visszaadni egy user csoporttagsagait, meg van egy fuggveny, ami a csoport tagjait adja vissza. A gond az, hogy valamiert az _alrendszer_ implicite meghivja ezeket a set-generatorokat (nyilvan a feladat megoldasahoz nincs szukseg meghivni minden oldalon mindegyiket).
topicindito: nem lehet, h valami cachinget kikapcsolni, hogy csak akkor hivja meg a proxy fuggvenyeket, ha explicit referencia van ra? NagyZ biztos tudja a megoldast...
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
Nincsenek proxy függvények, mivel, mint említettem, ez egy LdapTemplate alapú megoldás, aminek semmi köze a perzisztencia frameworkokhoz (pl. Hibernate, effektíve próbálom leprogramozni, hogy minél jobban hasonlítsanak az LDAP-os entitások a Hibernates domain objektumokhoz), amelyek automatikusan generálnak ilyen proxykat. Egy lazy-loading jellegű proxyt valószínűleg én is össze tudnék dobni, csak nem szeretnék, mert nem 10 perces meló. :)
- A hozzászóláshoz be kell jelentkezni
Ha kitorlom a proxy fuggvenyeket, akkor sincs megoldas? Vagyis, megmondani a framework-nek, hogy _ne_ deserializalja az LDAP-bol a cuccokat?
J2EE-hez igen keveset ertek, de ugy tudom, valamennyire konfigolhato.
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
Lehet, hogy rosszul fogalmaztam. A spring-ldap LdapTemplatenek, nincsen ORM képessége. Vagyishogy van, de kizárlóag kézi mappeléssel. Tehát nem annyira okos, mint egy Hibernate, hogy az adatbázis relációkból néhány annotáció segítségével domain modellt kreáljon. Az LdapTemplate használatával gyakorlatilag annyit nyerek, hogy megkímél az unalmas és hosszadalmas "plumbing code" írásától és, hogy lehetőséget biztosít viszonylag elegánsan és könnyedén LDAP entry -> Java entitás leképezésre, de szigorúan kézzel megírva. A frameworknak megmondható, hogy ne hozza fel végtelenségig az egymásba ágyazott asszociációkat, hiszen kézzel mappelek, de ez így első elgondolásra valamilyen ritka hányadék megoldáshoz fog vezetni, hiszen a mappelő interfészek alapból nem tudják, hogy ők a reláció melyik oldalán állnak és hogy milyen mélységig kellene "lemenniók". Hibernate ezt úgy oldja meg, hogy lecseréli a Set implementációt a saját PersistentSetjére, ami fel van készítve lazy-loadingra, így mindig csak akkor tölti tovább az asszociációt, hogyha valóban hivatkozunk a Set elemekre. A Lazy-loading helyes megvalósítása viszont egyáltalán nem triviális.
- A hozzászóláshoz be kell jelentkezni
Viszont a hanyadek megoldas lehet, hogy egyszerubb ut a boldogsaghoz.
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
Egyébként valószínűleg mégis lazy-loading lesz és csinálok egy olyan Set implementációt, ami csak akkor tölti be az adatait, hogyha tényleg kell.
- A hozzászóláshoz be kell jelentkezni