Proxy in slaapstand load () -methode

1. Overzicht

In deze tutorial zullen we zien wat een proxy is in de context van Hibernate's laden() methode.

Voor lezers die nieuw zijn bij Hibernate, overweeg om eerst vertrouwd te raken met de basisprincipes.

2. Een korte inleiding tot proxy's en laden() Methode

Per definitie is een gevolmachtigde "een functie die bevoegd is om op te treden als plaatsvervanger of vervanger van een ander".

Dit is van toepassing op Hibernate wanneer we bellen Session.load () om een ​​zogenaamd niet-geïnitialiseerde proxy van onze gewenste entiteitsklasse.

Simpel gezegd, Hibernate onderverdeelt onze entiteitsklasse met behulp van de CGLib bibliotheek. Anders dan de @ID kaart methode, delegeert de proxy-implementatie alle andere eigenschapsmethoden naar de Hibernate-sessie om de instantie te vullen, ongeveer als:

openbare klasse HibernateProxy breidt MyEntity {privé MyEntity-doel uit; openbare String getFirstName () {if (target == null) {target = readFromDatabase (); } retourneer target.getFirstName (); }}

Deze subklasse zal worden geretourneerd in plaats van rechtstreeks de database te doorzoeken.

Zodra een van de entiteitsmethoden is aangeroepen, wordt de entiteit geladen en wordt op dat punt een geïnitialiseerde proxy.

3. Proxy's en lui bezig met laden

3.1. Een enkele entiteit

Laten we erover nadenken Werknemer als een entiteit. Om te beginnen gaan we ervan uit dat het geen relatie heeft met andere tabellen.

Als we Session.load () om een Werknemer:

Medewerker albert = session.load (Employee.class, new Long (1));

Vervolgens maakt Hibernate een niet-geïnitialiseerde proxy van Werknemer. Het bevat de ID die we eraan hebben gegeven, maar verder heeft het geen andere waarden omdat we de database nog niet hebben bereikt.

Zodra we echter een methode aanroepen albert:

String firstName = albert.getFirstName ();

Vervolgens vraagt ​​Hibernate het werknemer databasetabel voor een entiteit met een primaire sleutel van 1, die wordt gevuld albert met zijn eigendommen uit de bijbehorende rij.

Als het geen rij kan vinden, gooit Hibernate een ObjectNotFoundException.

3.2. Een-op-veel relaties

Laten we nu een Bedrijf entiteit ook, waarbij a Bedrijf heeft veel Werknemers:

openbare klasse Bedrijf {privé Stringnaam; privé Set medewerkers; }

Als we deze keer gebruiken Session.load () op het bedrijf:

Company bizco = session.load (Company.class, new Long (1)); Tekenreeksnaam = bizco.getName ();

Dan worden de eigendommen van het bedrijf zoals voorheen bevolkt, behalve dat het aantal werknemers net iets anders is.

Kijk, we hebben alleen naar de bedrijfsrij gevraagd, maar de proxy laat de werknemer met rust totdat we bellen getEmployees afhankelijk van de ophaalstrategie.

3.3. Veel-op-een-relaties

Het geval is vergelijkbaar in de tegenovergestelde richting:

openbare klasse Medewerker {private String firstName; privé bedrijfswerkplek; }

Als we laden() opnieuw:

Employee bob = session.load (Employee.class, new Long (2)); String firstName = bob.getFirstName ();

Bob wordt nu geïnitialiseerd, en eigenlijk, werkplek wordt nu ingesteld als een niet-geïnitialiseerde proxy, afhankelijk van de ophaalstrategie.

4. Lui-achtig laden

Nu, laden() zal ons niet altijd een niet-geïnitialiseerde proxy geven. In feite is de Sessie java doc herinnert ons eraan (nadruk toegevoegd):

Deze methode macht retourneert een proxy-instantie die op aanvraag is geïnitialiseerd, wanneer een niet-identificatiemethode wordt benaderd.

Een eenvoudig voorbeeld van wanneer dit kan gebeuren, is de batchgrootte.

Laten we zeggen dat we gebruiken @Seriegrootte op onze Werknemer entiteit:

@Entity @BatchSize (size = 5) klasse Medewerker {// ...}

En dit keer hebben we drie medewerkers:

Medewerker catherine = session.load (Employee.class, new Long (3)); Employee darrell = session.load (Employee.class, new Long (4)); Medewerker emma = session.load (Employee.class, new Long (5));

Als we bellen getFirstName Aan catherine:

String cathy = catherine.getFirstName ();

Vervolgens kan Hibernate besluiten om alle drie de werknemers tegelijk te laden, waardoor ze alle drie worden omgezet in geïnitialiseerde proxy's.

En dan, als we erom vragen darrellVoornaam:

String darrell = darrell.getFirstName ();

Dan Hibernate komt helemaal niet in de database.

5. Gretig laden

5.1. Gebruik makend van krijgen()

We kunnen proxy's ook volledig omzeilen en Hibernate vragen om het echte werk te laden met Session.get ():

Werknemer finnigan = session.get (Employee.class, new Long (6));

Dit zal de database meteen aanroepen, in plaats van een proxy terug te sturen.

En eigenlijk, in plaats van een ObjectNotFoundException, het zal terugkeren nul als Finnigan bestaat niet.

5.2. Prestatiesimplicaties

Terwijl krijgen() is handig, laden() kan lichter zijn op de database.

Laten we bijvoorbeeld zeggen Gerald gaat werken voor een nieuw bedrijf:

Medewerker gerald = session.get (Employee.class, new Long (7)); Company worldco = (Company) session.load (Company.class, new Long (2)); employee.setCompany (worldco); session.save (medewerker);

Omdat we weten dat we alleen de werknemer record in deze situatie, roeping laden() voor Bedrijf is verstandig.

Als we belden krijgen() Aan Bedrijf, dan hadden we al zijn gegevens onnodig uit de database geladen.

6. Conclusie

In dit artikel hebben we kort geleerd hoe Slaapstand proxy's werken en hoe dit de laden methode met entiteiten en hun relaties.

We hebben ook snel gekeken hoe laden() is anders dan krijgen().

Zoals gewoonlijk is de volledige broncode die bij de tutorial hoort, beschikbaar op GitHub.