Vlákno názorů k článku Entity beans v JBoss a relace od pavel - Relace, které mají na druhé straně N (tj....

  • Článek je starý, nové názory již nelze přidávat.
  • 3. 12. 2008 13:49

    pavel (neregistrovaný)
    Relace, které mají na druhé straně N (tj. 1:N a M:N) se standardně načítají lenivě (viz specifikace, kapitoly 9.1.24 a 9.1.26). U vazby M:N je to dále v článku uvedeno, nicméně příklad s lenivým načítáním 1:N mi připadá matoucí (protože je to default).

    Dále ještě doplním, že pokud bude velké množství relací fetchované eager, tak se v horším případě může stát, že se do paměti natáhne celá DB. V lepším případě se natáhne "pouze" velký strom objektů. Proti tomu se při použití JPA implementace v Hibernate lze bránit nastavením maximální hloubky, do které se rekurzivně entity fetchují eager (parametr hibernate.max_fetch_depth). Kromě toho je vhodné se zamyslet nad tím, jestli je skutečně potřeba vše fetchovat eager.

    A ještě postřeh z používání JPA implementace v Hibernate. Eager fetch mi vždy fungoval pouze pokud jsem loadoval jedinou entitu (např. pomocí EntityManager.find nebo pomocí lenivého fetche relace N:1). Ve všech ostatních případech (např. dotaz vracející kolekci entit nebo lenivý fetch relace 1:N) byl load navázaných entit vždy lenivý bez ohledu na nastavení anotací. V případě dotazů to lze obejít pomocí fetch joinů, ale pozor na to, že potom může dojít k duplikaci záznamů. Nevím, jestli popsané chování je bug nebo feature, ve specifikaci jsem to nehledal, ale připadá mi celkem logické.
  • 3. 12. 2008 14:55

    Palo (neregistrovaný)
    Zalezi ako velmi Enterprise to mate vyriesene. Pre male riesenia kde mate Webovu vrstvu pokope s entitnou v jednom virtualnom stroji je to OK. Ale pre velke enterprise riesenia kde mate skutocne entitnu/servisnu vrstvu separatne je lazy loading dobry iba pre sluzby, web uz si ich lazy nanataha. Taktiez pre riesenia s ESB (SOA) lazy velmi nepomoze.
  • 5. 12. 2008 12:17

    antaran (neregistrovaný)
    RE:

    V případě dotazů to lze obejít pomocí fetch joinů, ale pozor na to, že potom může dojít k duplikaci záznamů. Nevím, jestli popsané chování je bug nebo feature, ve specifikaci jsem to nehledal, ale připadá mi celkem logické.

    Ahoj

    Nie je my jasne preco dochadza k duplikacii zaznamov pri fetch joine???
    (k duplikacii akych zaznamov? preco ti to pripada logicke?)

    nejaky priklad by som odcenil...

    Diq

    ant
  • 6. 12. 2008 11:41

    pavel (neregistrovaný)

    Pomůžu si citací ze specifikace (kapitola 4.4.5.3):

    The following query returns a set of departments. As a side effect, the associated employees for those departments are also retrieved, even though they are not part of the explicit query result. The persistent fields or properties of the employees that are eagerly fetched are fully initialized. The initialization of the relationship properties of the employees that are retrieved is determined by the metadata for the Employee entity class.

    SELECT d FROM Department d LEFT JOIN FETCH d.employees WHERE d.deptno = 1

    A fetch join has the same join semantics as the corresponding inner or outer join, except that the related objects specified on the right-hand side of the join operation are not returned in the query result or otherwise referenced in the query. Hence, for example, if department 1 has five employees, the above query returns five references to the department 1 entity.

    Za popsaných podmínek tedy tento dotaz vrátí 5 departmentů (5 krát ten samý), přestože department s číslem 1 existuje pouze jeden. Bez použití klauzule LEFT JOIN FETCH by se vrátil jediný záznam. Zaměstnance by bylo defaultně nutné dotáhnout lenivě.

    Citovaný text zároveň říká, že při vyhodnocení dotazu se korektně dotáhnou relace podle nastavení v anotacích. Mnou popsané chování Hibernate tedy pravděpodobně byl bug nějaké starší verze. Zkoušel jsem to znovu a nyní se skutečně Hibernate chová v souladu se specifikací, takže se omlouvám za mystifikaci.

    A proč mi to připadalo logické? Protože mám možnost si explicitně referencované entity dotáhnout pomocí fetch joinu, pokud to potřebuji, nebo je nedotahovat, pokud to nepotřebuji. Automatické dotažení entit nemusí být vždy efektivní. Např. pokud ve výše uvedeném příkladu budu mít Employees dotahované eager, tak Hibernate udělá jeden dotaz na Department a potom bude postupně dotahovat Employees po skupinách o velikosti hibernate.default_batch_fetch_size. Počet dotazů do DB je tedy lineárně závislý na počtu instancí entity Department. Tohle se žádnému DBA líbit nebude... Pokud se budou Employees dotahovat lenivě, tak se provede to samé, ale až při prvním přístupu ke kolekci Employees. Pokud tedy logika aplikace pracuje pouze s Departmenty, tak stačí jediný dotaz do DB.

  • 7. 12. 2008 1:54

    antaran (neregistrovaný)
    aha, vdaka za objasnenie... :)

    to, ze je vyslednych zaznamov 5 nieje prekvapujuce, je to proste to iste ako obycajny LEFT JOIN, akurat ze vyslednych employees nemas v select casti, ale su pekne vrateni cez Set v Department...