Konfigurace JPA ve Spring s hibernate OpenSessionInViewInterceptor

Jiří Hradil jirka na hradil.cz
Neděle Leden 25 17:20:46 CET 2009


Dobrý den,

děkuji všem za odpovědi. Dnešek jsem strávil detailním studiem
uvedeného a už je mi to úplně jasné :). Samozřejmě máte pravdu a je to
přesně tak, jak popisujete-obalením do transakce je persistence
context stále přístupný a lazy loading funguje v pořádku. Zabijákem
myšlenek bylo v tomto případě nové použití Hibernate jako JPA
providera, protože v Toplink Essentials JPA, na který jsem zvyklý, se
popsaný problém nevyskytuje. Lazy loading v Toplinku funguje i v
případě, že ho zavolám mimo transakci, nevím, zda je to implementační
detail, něco jsem přehlédl, nebo Toplink fungoval stále ve
FetchType.EAGER, protože jsem mu nepředhodil weaver.

Jinak ty interceptory a filtry pro open view - doteď se mi je
nepodařilo s web vrstvou rozchodit. Zkoušel jsem napojení na Apache
Wicket a i když se v konferencích o Wicketu jeví jejich použití jako
funkční, nepodařilo se mi podržet session otevřenou. Problém však
vyřeším načítáním kolekcí přes lazy v service vrstvě (v transakci),
což mi umožní líp reflektovat používané případy užití aplikace
(naplním do entity jen to, co view bude potřebovat). Nechci nechat na
view, aby si rozhodoval, co chce přes lazy donačíst, protože to IMHO
není správný přístup. Pokud se používá čisté JPA bez anotačního
rozšíření Hibernate, ve kterém lze omezit velikost vrácené kolekce,
tak by view vrstva snadno mohla způsobit výkonnostní problém.

Přikládám aktualizovanou verzi projektu, znatelně zjednodušenou v
využívající pro junit testy Spring. Kdyby to někdo v budoucnu
potřeboval, ať to najde.

Děkuji,

Jirka Hradil

On Sun, Jan 25, 2009 at 2:11 PM, Martin Kočí <Martin.Koci na aura.cz> wrote:
> Zdravím,
>
> OpenEntityManagerInViewInterceptor i OpenEntityManagerInViewFilter jsou
> záležitosti čistě webové (interceptor implementuje
> spring.WebRequestInterceptor, filter spring.OncePerRequestFilter),
> jejich registrace nemá žádný vliv na to, jak se lazy loading chová v
> testech - tam se ani jeden z uvedených typů nedostane ke slovu.
>
> Klíčové pro pochopení lazy loading je doba životnosti tzv.
> persistentního kontextu. JPA definuje dva rozsahy (viz JPA spec. část
> Persistence Context Lifetime):
>
> 1) Transaction
> 2) Extended
>
> přičemž Transaction je default. Pro funkční lazy loading platí, že se
> nesmí zrušit persistentní kontext, ve kterém byla asociace
> (reprezentovaná runtime nějakou proxy třídou, v příkladu asocociace
> emails)  načtena. V uvedeném příkladě zanikne persistentní kontext již
> po dokončení metody dao.findById(result.getId()), takže následující
> volání getEmails() vyhodí LazyInitException.
>
> Váš problém vyřeší, pokud si převedete  "business transakci 'Načtení
> osoby a emailů'" do jedné metody označené @Transactional:
>
> @Transactional
>  public List<Email> getEmails(Person person) {
>  dao.findById(person.getId());
>  return person.getEmails();
> }
>
> to bude fungovat, protože persistentní kontext je "roztažen" přes celou
> transakci.
>
> Poznámka: ani OpenEntityManagerInViewFilter vás nezbaví
> LazyInitException "trvale", pouze pro asociace, ke kterým se přistupuje
> v  rámci jednoho request/response. Např. pro lazyloading spolu se
> stránkováním pomocí query.setMaxResult() potřebujete "roztáhnout"
> persistentní kontext na "větší" scope než je request, např. podle
> http://www.hibernate.org/43.html.
>
>
>
>
>
> Jiří Hradil píše v So 24. 01. 2009 v 11:39 +0100:
>> OpenEntityManagerInViewInterceptor
>
>
------------- další část ---------------
A non-text attachment was scrubbed...
Name: HibernateJpaMaven-2.zip
Type: application/zip
Size: 12573 bytes
Desc: [žádný popis není k dispozici]
URL: <http://amaio.cz/pipermail/konference/attachments/20090125/2dfc1ece/attachment.zip>


Další informace o konferenci Konference