Gretig / lui laden in slaapstand

Persistentie top

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS

1. Inleiding

Wanneer u met een ORM werkt, kan het ophalen / laden van gegevens worden ingedeeld in twee typen: gretig en lui.

In dit korte artikel gaan we op verschillen wijzen en laten we zien dat deze kunnen worden gebruikt in Hibernate.

2. Maven afhankelijkheden

Laten we, om Hibernate te gebruiken, eerst de belangrijkste afhankelijkheid in ons pom.xml:

 org.hibernate hibernate-core 5.2.2.Final 

De nieuwste versie van Hibernate is hier te vinden.

3. Gretig en lui laden

Het eerste dat we hier moeten bespreken, is wat lazy loading en gretig laden zijn:

  • Gretig laden is een ontwerppatroon waarin data-initialisatie ter plekke plaatsvindt
  • Trage voortgang is een ontwerppatroon dat wordt gebruikt om de initialisatie van een object zo lang mogelijk uit te stellen

Laten we eens kijken hoe dit echt werkt met enkele voorbeelden:

De GebruikerLazy klasse:

@Entity @Table (name = "USER") openbare klasse UserLazy implementeert Serializable {@Id @GeneratedValue @Column (name = "USER_ID") privé Lange userId; @OneToMany (fetch = FetchType.LAZY, mappedBy = "gebruiker") privé Stel orderDetail = nieuwe HashSet (); // standaard setters en getters // overschrijven ook gelijken en hashcode}

De OrderDetail klasse:

@Entity @Table (name = "USER_ORDER") openbare klasse OrderDetail implementeert Serializable {@Id @GeneratedValue @Column (name = "ORDER_ID") privé Long orderId; @ManyToOne (fetch = FetchType.LAZY) @JoinColumn (naam = "USER_ID") privé UserLazy-gebruiker; // standaard setters en getters // overschrijven ook gelijken en hashcode}

een Gebruiker kan meerdere hebben Bestel Details. Bij een gretige laadstrategie, als we het Gebruiker gegevens, zal het ook alle bijbehorende orders laden en in een geheugen opslaan.

Maar als lazy loading is ingeschakeld, als we een GebruikerLazy, OrderDetail gegevens worden niet geïnitialiseerd en in een geheugen geladen totdat er expliciet een oproep naar wordt gedaan.

In de volgende sectie zullen we zien hoe het bovenstaande voorbeeld wordt geïmplementeerd in Hibernate.

4. Configuratie laden

In deze sectie zullen we bekijken hoe we ophaalstrategieën in Hibernate kunnen configureren. We zullen voorbeelden uit de vorige sectie hergebruiken.

Lazy Loading kan eenvoudig worden ingeschakeld met behulp van de volgende annotatieparameter:

fetch = FetchType.LAZY

Om Eager Fetching te gebruiken, wordt de volgende parameter gebruikt:

fetch = FetchType.EAGER

Om Eager Loading in te stellen hebben we gebruikt GebruikerLazy‘S twin class genoemd UserEager.

In de volgende sectie zullen we de verschillen tussen de twee soorten ophaalacties bekijken.

5. Verschillen

Zoals we al zeiden, is het belangrijkste verschil tussen de twee soorten ophaalacties het moment waarop gegevens in een geheugen worden geladen.

Laten we dit voorbeeld eens bekijken:

Lijst gebruikers = sessionLazy.createQuery ("Van UserLazy"). List (); UserLazy userLazyLoaded = users.get (3); terugkeer (userLazyLoaded.getOrderDetail ());

Met de luie initialisatiebenadering, orderDetailSet wordt alleen geïnitialiseerd als het expliciet wordt aangeroepen met behulp van een getter of een andere methode, zoals weergegeven in het bovenstaande voorbeeld:

UserLazy userLazyLoaded = users.get (3);

Maar met een gretige aanpak erin UserEager het wordt onmiddellijk geïnitialiseerd in de eerste regel van het bovenstaande voorbeeld:

Lijst gebruiker = sessionEager.createQuery ("Van UserEager"). List ();

Voor lazy loading wordt een proxy-object gebruikt en wordt een aparte SQL-query geactiveerd om het orderDetailSet .

Het idee om proxy's of lazy loading uit te schakelen, wordt in Hibernate als een slechte gewoonte beschouwd. Het kan ertoe leiden dat veel gegevens uit een database worden opgehaald en in een geheugen worden opgeslagen, ongeacht de noodzaak ervan.

De volgende methode kan worden gebruikt om de bovenstaande functionaliteit te testen:

Hibernate.isInitialized (orderDetailSet);

Nu is het belangrijk om de queries te bekijken die in beide gevallen worden gegenereerd:

waar

De bovenstaande instelling in de fetching.hbm.xml toont de SQL-query's die worden gegenereerd. Als u naar een console-uitvoer kijkt, kunt u gegenereerde query's zien.

Voor Lazy Loading: de query die wordt gegenereerd om het Gebruiker gegevens:

selecteer user0_.USER_ID als USER_ID1_0_, ... van USER user0_

Bij het gretig laden zagen we echter een verbinding worden gemaakt USER_ORDER:

selecteer orderdetai0_.USER_ID als USER_ID4_0_0_, orderdetai0_.ORDER_ID als ORDER_ID1_1_0_, orderdetai0_ ... van USER_ORDER orderdetai0_ waar orderdetai0_.USER_ID =?

De bovenstaande vraag is voor iedereen gegenereerd Gebruikers, wat ertoe leidt dat er veel meer geheugen wordt gebruikt dan bij de andere benadering.

6. Voordelen en nadelen

6.1. Trage voortgang

Voordelen:

  • De initiële laadtijd is veel kleiner dan bij de andere benadering
  • Minder geheugengebruik dan bij de andere benadering

Nadelen:

  • Een vertraagde initialisatie kan de prestaties beïnvloeden tijdens ongewenste momenten
  • In sommige gevallen moet u lui geïnitialiseerde objecten met speciale zorg behandelen, anders krijgt u mogelijk een uitzondering

6.2. Gretig laden:

Voordelen:

  • Geen invloed op de prestaties met betrekking tot vertraagde initialisatie

Nadelen:

  • Lange initiële laadtijd
  • Het laden van te veel onnodige gegevens kan de prestaties beïnvloeden

7. Lui laden in slaapstand

Hibernate past een lazy loading-benadering toe op entiteiten en associaties door een proxy-implementatie te bieden van klassen.

Hibernate onderschept oproepen naar een entiteit door deze te vervangen door een proxy die is afgeleid van de klasse van een entiteit. Als in ons voorbeeld een opgevraagde informatie ontbreekt, wordt deze uit een database geladen voordat de controle wordt overgedragen aan het Gebruiker klasse implementatie.

Er moet ook worden opgemerkt dat wanneer de associatie wordt weergegeven als een verzamelingsklasse (in de bovenstaande voorbeelden wordt deze weergegeven als Stel orderDetailSet in), dan wordt een wrapper gemaakt en vervangen door een originele collectie.

Voor meer informatie over het proxy-ontwerppatroon kunt u hier verwijzen.

8. Conclusie

In dit artikel hebben we voorbeelden laten zien van de twee belangrijkste soorten ophaalacties die in Hibernate worden gebruikt.

Voor geavanceerde expertise kunt u kijken op de officiële website van Hibernate. Bekijk deze repository om de code te krijgen die in dit artikel wordt besproken.

Persistentie onderaan

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS