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

Odpovedet emailem