Grafikon entiteta JPA

1. Pregled

JPA 2.1 predstavio je značajku Entity Graph kao sofisticiraniju metodu rješavanja opterećenja performansi.

Omogućuje definiranje predloška grupiranjem povezanih polja trajnosti koja želimo dohvatiti i omogućuje nam odabir vrste grafa tijekom izvođenja.

U ovom uputstvu detaljnije ćemo objasniti kako stvoriti i koristiti ovu značajku.

2. Što entitetski grafikon pokušava riješiti

Do JPA 2.0, za učitavanje udruživanja entiteta, obično smo koristili FetchType.LIJEN i FetchType.ŽELJAN kao strategije dohvaćanja. Ovo upućuje pružatelja usluga JPA da dodatno dohvati povezano povezivanje ili ne. Nažalost, ova meta konfiguracija je statična i ne dopušta prebacivanje između ove dvije strategije tijekom izvođenja.

Glavni cilj grafikona entiteta JPA je tada poboljšati izvedbene performanse prilikom učitavanja povezanih entiteta i osnovnih polja entiteta.

Ukratko, JPA davatelj učitava sve grafikone u jedan odabrani upit, a zatim izbjegava dohvaćanje povezanosti s više SELECT upita. Ovo se smatra dobrim pristupom za poboljšanje izvedbe aplikacije.

3. Definiranje modela

Prije nego što započnemo s istraživanjem grafikona entiteta, moramo definirati entitete modela s kojima radimo. Recimo da želimo stvoriti web lokaciju bloga na kojoj korisnici mogu komentirati i dijeliti postove.

Dakle, prvo ćemo imati Korisnik entitet:

@Entity javna klasa Korisnik {@Id @GeneratedValue (strategija = GenerationType.IDENTITY) private Long id; privatni naziv niza; privatni String e-mail; // ...}

Korisnik može dijeliti razne postove, pa nam također treba Objavi entitet:

@Entity javna klasa Post {@Id @GeneratedValue (strategija = GenerationType.IDENTITY) private Long id; privatna niska; @OneToMany (mappedBy = "post") komentari privatnog popisa = new ArrayList (); @ManyToOne (fetch = FetchType.LAZY) @JoinColumn privatni korisnik; // ...}

Korisnik također može komentirati zajedničke postove, pa ćemo, napokon, dodati i Komentar entitet:

@Entity javna klasa Komentar {@Id @GeneratedValue (strategija = GenerationType.IDENTITY) private Long id; privatni odgovor u nizu; @ManyToOne (fetch = FetchType.LAZY) @JoinColumn privatni post; @ManyToOne (fetch = FetchType.LAZY) @JoinColumn privatni korisnik; // ...}

Kao što vidimo, Objavi entitet ima asocijaciju na Komentar i Korisnik entiteta. The Komentar entitet ima asocijaciju na Objavi i Korisnik entiteta.

Cilj je zatim na razne načine učitati sljedeći graf:

Objavi -> korisnik: Korisnik -> komentari: Popiši komentare [0]: Komentar -> korisnik: Korisnički komentari [1]: Komentar -> korisnik: Korisnik

4. Učitavanje povezanih entiteta sa FetchType Strategije

The FetchType metoda definira dvije strategije za dohvaćanje podataka iz baze podataka:

  • FetchType.EAGER: Pružatelj trajnosti mora učitati povezano anotirano polje ili svojstvo. Ovo je zadano ponašanje za @Basic, @ManyToOne, i @Jedan na jedan anotirana polja.
  • FetchType.LIJENO: Pružatelj trajnosti trebao bi učitati podatke kad im se prvi put pristupi, ali se mogu učitati s nestrpljenjem. Ovo je zadano ponašanje za @OneToMany, @ManyToMany i @ ElementCollection-anotirana polja.

Na primjer, kada učitamo a Objavi entitet, povezani Komentar entiteti nisu učitani kao zadani FetchType od @OneToMany je LIJEN. To ponašanje možemo nadvladati promjenom FetchType do ŽELJAN:

@OneToMany (mappedBy = "post", fetch = FetchType.EAGER) komentari privatnog popisa = new ArrayList ();

Za usporedbu, kada učitamo a Komentar entitet, njegov Objavi nadređeni entitet učitava se kao zadani način za @ManyToOne, koji je ŽELJAN. Također možemo odabrati da ne učitavamo Objavi entitetom promjenom ove bilješke u LIJEN:

@ManyToOne (fetch = FetchType.LAZY) @JoinColumn (name = "post_id") privatni post;

Imajte na umu da kao LIJEN nije uvjet, pružatelj trajnosti i dalje može učitati Objavi entitet željno ako želi. Dakle, da bismo pravilno koristili ovu strategiju, trebali bismo se vratiti službenoj dokumentaciji odgovarajućeg pružatelja trajnosti.

Budući da smo koristili napomene kako bismo opisali strategiju dohvaćanja, naša je definicija statična i ne postoji način za prebacivanje između LIJEN i ŽELJAN za vrijeme izvođenja.

Ovdje se pojavljuje Entity Graph, što ćemo vidjeti u sljedećem odjeljku.

5. Definiranje grafikona entiteta

Da bismo definirali grafikon entiteta, možemo upotrijebiti napomene na entitetu ili možemo programski nastaviti pomoću JPA API-ja.

5.1. Utvrđivanje grafikona entiteta s bilješkama

@NamedEntityGraph anotacija omogućuje specificiranje atributa koji se uključuju kada želimo učitati entitet i povezane asocijacije.

Pa prvo definirajmo Entity Graph koji učitava Objavi i njegovih povezanih entiteta Korisnik i Komentars:

@NamedEntityGraph (name = "post-entity-graph", attributeNodes = {@NamedAttributeNode ("subject"), @NamedAttributeNode ("user"), @NamedAttributeNode ("comments",}) @ Entity public class Post {@OneToMany (mappedBy = "post") komentari privatnog popisa = novi ArrayList (); // ...}

U ovom smo primjeru koristili @NamedAttributeNode za definiranje povezanih entiteta koji će se učitati kada se učita korijenski entitet.

Ajmo sada definirati složeniji Entity Graph gdje želimo također učitati Korisniks povezanim sa Komentars.

U tu svrhu koristit ćemo @NamedAttributeNode atribut podgrafa. To omogućuje referenciranje imenovanog podgrafa definiranog pomoću @NamedSubgraph napomena:

@NamedEntityGraph (name = "post-entity-graph-with-comment-users", attributeNodes = {@NamedAttributeNode ("subject"), @NamedAttributeNode ("user"), @NamedAttributeNode (value = "comments", subgraph = " comments-subgraph "),}, subgraphs = {@NamedSubgraph (name =" comments-subgraph ", attributeNodes = {@NamedAttributeNode (" user ")})}) @ Entity javna klasa Post {@OneToMany (mappedBy =" post " ) komentari privatnog popisa = novi ArrayList (); // ...}

Definicija @NamedSubgraph napomena slična je znaku @NamedEntityGraph i omogućuje specificiranje atributa povezane asocijacije. Na taj način možemo konstruirati cjeloviti graf.

U gornjem primjeru, s definiranim "post-entity-graph-with-comment-users ' grafikon, možemo učitati Post, srodnih Korisnik, the Komentari i Korisniks povezane sa Komentari.

Na kraju, imajte na umu da možemo alternativno dodati definiciju grafikona entiteta pomoću orm.xml deskriptor implementacije:

  ...     ... 

5.2. Definiranje grafikona entiteta pomoću JPA API-ja

Također možemo definirati grafikon entiteta putem EntityManager API pozivanjem createEntityGraph () metoda:

EntityGraph entityGraph = entityManager.createEntityGraph (Post.class);

Da bismo odredili atribute korijenskog entiteta, koristimo addAttributeNodes () metoda.

entityGraph.addAttributeNodes ("predmet"); entityGraph.addAttributeNodes ("korisnik");

Slično tome, da bismo uključili atribute povezanog entiteta, koristimo addSubgraph () konstruirati ugrađeni Entity Graph, a zatim mi addAttributeNodes () kao što smo to učinili gore.

entityGraph.addSubgraph ("komentari") .addAttributeNodes ("korisnik");

Sad kad smo vidjeli kako stvoriti Entity Graph, istražit ćemo kako ga koristiti u sljedećem odjeljku.

6. Korištenje grafikona entiteta

6.1. Vrste grafikona entiteta

JPA definira dva svojstva ili savjete pomoću kojih davatelj trajnosti može odabrati kako bi učitao ili dohvatio grafikon entiteta u vrijeme izvođenja:

  • javax.persistence.fetchgraph - Iz baze podataka dohvaćaju se samo navedeni atributi. Kako u ovom vodiču koristimo Hibernate, možemo primijetiti da su, za razliku od JPA specifikacija, atributi statički konfigurirani kao ŽELJAN su također učitani.
  • javax.persistence.loadgraph - Uz navedene atribute, atributi statički konfigurirani kao ŽELJAN su također dohvaćeni.

U oba slučaja uvijek su učitani primarni ključ i verzija ako postoji.

6.2. Učitavanje grafikona entiteta

Grafikon entiteta možemo dobiti na razne načine.

Krenimo od EntityManager.find() metoda. Kao što smo već pokazali, zadani način rada temelji se na statičkim meta-strategijama FetchType.EAGER i FetchType.LIJENO.

Pa prizovimo se pronaći() metoda i pregledavanje dnevnika:

Objavi post = entityManager.find (Post.class, 1L);

Evo dnevnika koji pruža implementacija hibernacije:

odaberite post0_.id kao id1_1_0_, post0_.subject kao subject2_1_0_, post0_.user_id kao user_id3_1_0_ iz Post post0_ gdje post0_.id =?

Kao što vidimo iz dnevnika, Korisnik i Komentar entiteti nisu učitani.

To nadmašeno ponašanje možemo nadjačati pozivanjem preopterećenog pronaći() metoda koja prihvaća savjete kao a Karta. Tada možemo pružite vrstu grafa koju želimo učitati:

EntityGraph entityGraph = entityManager.getEntityGraph ("grafikon post-entiteta"); Svojstva karte = novi HashMap (); svojstva.put ("javax.persistence.fetchgraph", entityGraph); Objavi post = entityManager.find (Post.class, id, svojstva);

Ako ponovno pogledamo u zapisnik, možemo vidjeti da su ovi entiteti sada učitani i samo u jednom odabranom upitu:

izberite post0_.id kot id1_1_0_, post0_.subject kot subject2_1_0_, post0_.user_id kot user_id3_1_0_, comments1_.post_id kot post_id3_0_1_, comments1_.id kot id1_0_1_, comments1_.id kot id1_0_2_, comments__id_odid_0_id_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odstavka_od_odgovora_, komentar_od_odstavka_od_odnosa_, komentar_od_odstavka_od_odstavka_od_odgovora_, komentar_odstavke_0_ do_odnosa_od_odgovora_od_odgovora_0_0_07_201_2010. .user_id kao user_id4_0_2_, user2_.id kao id1_2_3_, user2_.email kao email2_2_3_, user2_.name kao name3_2_3_ iz posta post0_ left external join Komentiraj komentare1_ na post0_.id = comments1_.post_id left external join User2_ na post0_.user_id = user2_. id gdje je post0_.id =?

Pogledajmo kako možemo postići istu stvar pomoću JPQL-a:

EntityGraph entityGraph = entityManager.getEntityGraph ("post-entity-graph-with-comment-users"); Objavi post = entityManager.createQuery ("odaberite p iz Post p gdje je p.id =: id", Post.class) .setParameter ("id", id) .setHint ("javax.persistence.fetchgraph", entityGraph) .getSingleResult ();

I na kraju, pogledajmo a Kriteriji Primjer API-ja:

EntityGraph entityGraph = entityManager.getEntityGraph ("post-entity-graph-with-comment-users"); CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder (); CriteriaQuery criteriaQuery = criteriaBuilder.createQuery (Post.class); Korijen korijena = kriterijiQuery.from (Post.class); kriterijiQuery.where (kriterijiBuilder.equal (root.get ("id"), id)); TypedQuery typedQuery = entityManager.createQuery (kriterijQuery); typedQuery.setHint ("javax.persistence.loadgraph", entityGraph); Objavi post = typedQuery.getSingleResult ();

U svakom od njih, vrsta grafa daje se kao savjet. Dok smo u prvom primjeru koristili Karta, u dva kasnija primjera koja smo koristili setHint () metoda.

7. Zaključak

U ovom smo članku istražili upotrebu grafikona JPA entiteta za dinamičko dohvaćanje Entitet i njegovih udruga.

Odluka se donosi u vrijeme izvođenja u kojem smo odlučili učitati ili ne povezati povezano povezivanje.

Izvedba je očito ključni faktor koji treba uzeti u obzir prilikom dizajniranja JPA entiteta. JPA dokumentacija preporučuje upotrebu FetchType.LIJENO strategiju kad god je to moguće i grafikon entiteta kada trebamo učitati asocijaciju.

Kao i obično, sav je kôd dostupan na GitHub-u.


$config[zx-auto] not found$config[zx-overlay] not found