Lazy initialisering, Et Dvalemodus problem

Det er et populært unntak som mange Hibernate newbees møter. For å unngå dette unntaket må du forstå begrepet Lat Initialisering.

1) Når Dvalemodus leser data fra databasen, holdes dataene i økten. Du kan lagre referanser til dataene – for EKSEMPEL I HTTP-forespørselen. Når transaksjonen er begått og økten er stengt, kan du ikke laste inn ytterligere data med denne økten.

I det første eksemplet har Vi sett At Honning har en Samling Bie. Hvis vi laster Inn En Honningeksempel, Vil Hibernate ikke laste biene automatisk. Det er en god grunn til denne oppførselen. Tenk deg at du laster Inn Et Selskap og får alle bestillinger, bestillingsdetaljer og artikler. I utgangspunktet laster du det meste av databasen bare ved å laste inn et Enkelt Firmaobjekt. Dette vil resultere i et minneproblem. Derfor Hibernate laster bare det første objektet og erstatter samlinger av andre objekter av en proxy. Hvis du åpner proxyen, Bruker Dvalemodus den gjeldende økten til å initialisere proxyen og laste oppføringene fra databasen.

2) Tenk deg En Struts rammeverk søknad. Hvis Du ikke vet Struts: det er et rammeverk for å utvikle webapplikasjoner. Når en bruker ber om noe, for eksempel han har sendt inn et skjema på et nettsted, skjer følgende:

  • sentral servlet kalles
  • servlet slår opp programlogikk for forespørselen og kaller programlogikken
  • programlogikk åpner en økt, lagrer eller henter data
  • programlogikk lagrer hentet data i forespørselen og lukker økten
  • kontroll returnerer til servlet
  • servlet kaller en JSP for å gjengi dialogboksen
  • jsp bruker dataene i forespørselen

hva er konsekvensene av 1) og 2)? Når du ser gjennom prosessen 2) kan du se at økten allerede er stengt, når dialogen gjengis. Din søknad logikk er ferdig behandling. Hvis du ikke har initialisert noen objekter mens økten er åpen, vil du ikke kunne vise dem. Ta en titt pa folgende diagram, som forklarer situasjonene ganske bra. \newline

når du åpner et ikke-initialisert objekt, får Du En LazyInitializationException som forklarer at økten allerede er stengt.

images/c_architecture_sequence_diagram.jpg

Når kan dette skje? Jeg har nevnt At Hibernate kan kartlegge relasjoner. Tenk deg en klasseavdeling som har en rekke lag.

public class Department { private Integer id; private String name; private Set teams = new HashSet();

hvis du vil skrive ut en liste over avdelinger og lag i JSP, må du ikke bare hente alle forekomster av avdeling, men også alle forekomster av lag som er knyttet til en av avdelingene du henter.

jeg fortalte deg at alle relasjoner som standard hentes lat. Dette betyr at Når du henter en avdeling, Vil Hibernate ikke hente lagene, men opprette en proxy. Når du åpner et team, bruker proxyen gjeldende økt til å laste teamet fra databasen. En proxy kan bare hente data når økten er åpen.

når du har relasjoner i tilordningen, må du sørge for at objektet og relaterte objekter initialiseres så lenge økten er åpen.

det er tre løsninger på dette problemet:

  • Define lazy= «false» i kartleggingen din
  • Hent Eksplisitt de tilknyttede dataene i spørringen din
  • Gjør bruk av et triks og utsett slutten av økten til et senere tidspunkt når JSP allerede er gjengitt.

den første løsningen er farlig. Tenk deg et forhold som

Applikasjonbruker Hryvnias KeyAccounter Kunde ③ Selskap → alle kunder av selskap → alle bestillinger av kunder

Hver tilgang ville laste inn hele databasen. Vær veldig forsiktig når du setter lat til falsk.

den andre løsningen er enkel, men har noen advarsler. Trikset heter Open-Session-In-View og forklares i kapittel Open Session In Viewdelen heter » Levetid til visningen er gjengitt (Open-Session-In-View)».

den tredje løsningen initialiserer dataene før økten avsluttes.

Vi har to alternativer for å initialisere data.

Tilnærming a)

List honeys = session.createQuery("select h from Honey as h").list();for (Iterator iter = honeys.iterator(); iter.hasNext();) { Honey element = (Honey) iter.next(); log.debug(element); Hibernate.initialize(element.getBees());

Tilnærming b)

honeys = session.createQuery("select h from Honey as h left join fetch h.bees") .list()

hvis du bruker tilnærming a) må du ringe For å ringe Dvalemodus.initialiser på hver proxy. Hver samtale vil generere en spørring.

Tilnærming b) genererer en left join-setning. Vi vil bare kreve ett spørsmål.

Vurder å bruke b) hvis du spør mye data.

Du må være klar over en tilbaketrekning av denne tilnærmingen. Venstre sammenføyning resulterer i doble oppføringer For Faktura når det er flere ordrer. Tenk på den underliggende sql-spørringen, som fører til et resultat som

invoice 1, joined order line 1invoice 1, joined order line 2invoice 2, joined order line 1.....

Hibernate vil også legge fakturaen 1 flere ganger til resultatlisten.

du kan bruke følgende fremgangsmåte for å få unike fakturaer (ta en titt i kapittelet hql og Kriteriespørring for detaljerte eksempler):

session.createCriteria(Honey.class).setFetchMode("bees",FetchMode.JOIN) .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();session.createQuery("select h from Honey as h join fetch h.bees") .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();

Posted on

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.