Proxy u načinu Hibernate load ()

1. Pregled

U ovom uputstvu vidjet ćemo što je proxy u kontekstu hibernacije opterećenje() metoda.

Za čitatelje koji su tek započeli hibernaciju, prvo razmislite o upoznavanju osnova.

2. Kratki uvod u opunomoćenike i opterećenje() Metoda

Po definiciji, opunomoćenik je "funkcija ovlaštena da djeluje kao zamjenik ili zamjena za drugog".

To se odnosi na hibernaciju kada zovemo Session.load () stvoriti ono što se naziva neinicijalizirani opunomoćenik naše željene klase entiteta.

Jednostavno rečeno, Hibernate potklase naše klase entiteta, koristeći CGLib knjižnica. Osim @Iskaznica metodom, proxy implementacija delegira sve ostale metode svojstva na hibernacijsku sesiju kako bi popunila instancu, otprilike poput:

javna klasa HibernateProxy proširuje MyEntity {privatni cilj MyEntity; javni niz getFirstName () {if (target == null) {target = readFromDatabase (); } vratiti target.getFirstName (); }}

Ovaj će podrazred biti onaj koji će se vratiti umjesto izravnog upita prema bazi podataka.

Jednom kada se pozove jedna od metoda entiteta, entitet se učitava i u tom trenutku postaje inicijalizirani proxy.

3. Punomoćnici i lijeni Učitavam

3.1. Jedan entitet

Razmislimo o tome Zaposlenik kao entitet. Za početak ćemo pretpostaviti da to nema nikakve veze s bilo kojom drugom tablicom.

Ako koristimo Session.load () za instanciranje an Zaposlenik:

Zaposlenik albert = session.load (Employee.class, novi Long (1));

Tada će Hibernate stvoriti neinicijalizirani proxy za Zaposlenik. Sadržat će ID koji smo mu dali, ali u protivnom neće imati drugih vrijednosti jer još nismo pogodili bazu podataka.

Međutim, kad jednom pozovemo metodu albert:

Niz firstName = albert.getFirstName ();

Tada će Hibernate postaviti zaposlenik tablica baze podataka za entitet s primarnim ključem 1, popunjavanje albert sa svojim svojstvima iz odgovarajućeg reda.

Ako ne uspije pronaći red, Hibernate baca znak ObjectNotFoundException.

3.2. Odnosi jedan-prema-više

Ajmo sada stvoriti Društvo entitet, gdje a Društvo ima mnogo Zaposlenici:

tvrtka javne klase {naziv privatnog niza; zaposlenici privatnog Set-a; }

Ako ovaj put iskoristimo Session.load () o tvrtki:

Tvrtka bizco = session.load (Company.class, novi Long (1)); Naziv niza = bizco.getName ();

Tada se svojstva tvrtke naseljavaju kao i prije, samo što se skup zaposlenih samo malo razlikuje.

Vidite, tražili smo samo red tvrtke, ali proxy će zaposlenika ostaviti na miru dok ga ne nazovemo getEfficiees ovisno o strategiji dohvaćanja.

3.3. Veze s jednim

Slučaj je sličan u suprotnom smjeru:

zaposlenik u javnoj klasi {private String firstName; radno mjesto privatne tvrtke; }

Ako koristimo opterećenje() opet:

Employee bob = session.load (Employee.class, novi Long (2)); Niz firstName = bob.getFirstName ();

bob sada će se inicijalizirati, i zapravo, radno mjesto sada će biti postavljeno kao neinicijalizirani proxy, ovisno o strategiji dohvaćanja.

4. Lijeno učitavanje

Sada, opterećenje() neće nam uvijek dati neinicijalizirani proxy. Zapravo, Sjednica java doc podsjeća (naglasak dodan):

Ova metoda moć vrati proksiranu instancu koja se inicijalizira na zahtjev, kada se pristupi metodi koja nije identifikator.

Jednostavan primjer kada se to može dogoditi je veličina serije.

Recimo da koristimo @BatchSize na naš Zaposlenik entitet:

Zaposlenik klase @Entity @BatchSize (size = 5) {// ...}

I ovaj put imamo tri zaposlenika:

Zaposlenica catherine = session.load (Employee.class, novi Long (3)); Darrell zaposlenika = session.load (Employee.class, novi Long (4)); Emma zaposlenika = session.load (Employee.class, novi Long (5));

Ako nazovemo getFirstName na Katarina:

Niz cathy = catherine.getFirstName ();

Tada, zapravo, Hibernate može odlučiti učitati sve tri zaposlenike odjednom, pretvarajući sve tri u inicijalizirane proxyje.

I onda, kad to zatražimo darrellIme:

Niz darrell = darrell.getFirstName ();

Zatim Hibernate uopće ne pogađa bazu podataka.

5. Željno učitavanje

5.1. Koristeći dobiti()

Također možemo u potpunosti zaobići proxyje i tražiti Hibernate da učita stvarnu stvar pomoću Session.get ():

Zaposlenik finnigan = session.get (Employee.class, novi Long (6));

To će odmah nazvati bazu podataka, umjesto da vrati proxy.

I zapravo, umjesto ObjectNotFoundException, vratit će se null ako finnigan ne postoji.

5.2. Implikacije izvedbe

Dok dobiti() je prikladno, opterećenje() može biti lakši u bazi podataka.

Na primjer, recimo gerald će raditi za novu tvrtku:

Gerald zaposlenika = session.get (Employee.class, novi Long (7)); Company worldco = (Company) session.load (Company.class, novi Long (2)); zaposlenik.setCompany (worldco); session.save (zaposlenik);

Budući da znamo da ćemo samo promijeniti zaposlenik zapis u ovoj situaciji, pozivajući opterećenje() za Društvo je razumno.

Kad bismo nazvali dobiti() na Društvo, tada bismo nepotrebno učitali sve njegove podatke iz baze podataka.

6. Zaključak

U ovom smo članku ukratko naučili kako Hibernate punomoćnici rade i kako to utječe na opterećenje metoda s entitetima i njihovim odnosima.

Također, na brzinu smo pogledali kako opterećenje() razlikuje se od dobiti().

Kao i obično, puni izvorni kod koji prati udžbenik dostupan je na GitHubu.