Munka a Lazy Element Gyűjteményekkel a JPA-ban

Java Top

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

1. Áttekintés

A JPA specifikációja két különböző lekérési stratégiát tartalmaz: lelkes és lusta. Míg a lusta megközelítés segít elkerülni a szükségtelen adatok felesleges betöltését, olykor olyan adatokat kell olvasnunk, amelyeket eredetileg nem zárt perzisztencia-kontextusban töltöttünk be. Ezenkívül gyakori probléma a lusta elemgyűjteményekhez való hozzáférés zárt perzisztencia-kontextusban.

Ebben az oktatóanyagban arra összpontosítunk, hogyan töltsön be adatokat a lusta elemgyűjteményekből. Három különböző megoldást fogunk felfedezni: az egyik a JPA lekérdezési nyelvet foglalja magában, a másik az entitásdiagramok használatával, az utolsó pedig a tranzakcióterjesztéssel.

2. Az elemgyűjtési probléma

Alapértelmezés szerint a JPA a lusta letöltési stratégiát használja típusú társításokban @ElementCollection. Így a gyűjteményhez való hozzáférés zárt perzisztencia-környezetben kivételt eredményez.

A probléma megértése érdekében definiáljunk egy tartományi modellt az alkalmazott és a telefonlista közötti kapcsolat alapján:

@Entity public class Alkalmazott {@Id private int id; privát karakterlánc neve; @ElementCollection @CollectionTable (név = "alkalmazott_telefon", joinColumns = @JoinColumn (név = "alkalmazott_azonosító")) magánlista telefonok; // szabványos kivitelezők, mérőeszközök és beállítók} @Embeddable public class Phone {private String type; privát String areaCode; privát karakterlánc száma; // szabványos kivitelezők, mérőeszközök és beállítók}

Modellünk meghatározza, hogy egy alkalmazottnak sok telefonja lehet. A telefonlista a beágyazható típusok gyűjteménye. Használjunk egy tavaszi adattárat ezzel a modellel:

@Repository public class EmployeeRepository {public Employee findById (int id) {return em.find (Employee.class, id); } // további tulajdonságok és kiegészítő módszerek} 

Most ismételjük meg a problémát egy egyszerű JUnit tesztesettel:

public class ElementCollectionIntegrationTest {@Before public void init () előtt {Employee alkalmazott = új alkalmazott (1, "Fred"); worker.setPhones (Arrays.asList (új telefon ("munka", "+55", "99999-9999"), új telefon ("otthon", "+55", "98888-8888"))); workerRepository.save (alkalmazott); } @A nyilvános void után clean () {workerRepository.remove (1); } @Test (várható = org.hibernate.LazyInitializationException.class) public void whenAccessLazyCollection_thenThrowLazyInitializationException () {Employee alkalmazott = alkalmazottRepository.findById (1); assertThat (alkalmazott.getPhones (). méret (), az (2)); }} 

Ez a teszt kivételt hoz, amikor megpróbálunk hozzáférni a telefonlistához, mert a Perzisztencia kontextus zárva van.

Megoldhatjuk ezt a problémát a. letöltési stratégiájának megváltoztatása @ElementCollection hogy a lelkes megközelítést alkalmazza. Azonban lelkesen beolvasni az adatokat nem feltétlenül a legjobb megoldás, mivel a telefonadatok mindig betöltődnek, akár szükségünk van rá, akár nem.

3. Adatok betöltése a JPA lekérdezési nyelvvel

A JPA lekérdezési nyelve lehetővé teszi számunkra a kivetített információk testreszabását. Ezért meghatározhatunk egy új módszert a EmployeeRosory az alkalmazott és telefonjainak kiválasztásához:

public Employee findByJPQL (int id) {return em.createQuery ("SELECT u FROM Employee AS u JOIN FETCH u.phones WHERE u.id =: id", Employee.class) .setParameter ("id", id) .getSingleResult ( ); } 

A fenti lekérdezés belső csatlakozási műveletet használ a telefonlista lekéréséhez minden visszatért alkalmazottért.

4. Adatok betöltése entitásgráffal

Egy másik lehetséges megoldás a JPA entitásdiagram szolgáltatásának használata. Az entitásdiagram lehetővé teszi számunkra, hogy kiválasszuk, mely mezőket vetítik ki a JPA-lekérdezések. Határozzunk meg még egy módszert a tárunkban:

public Employee findByEntityGraph (int id) {EntityGraph entityGraph = em.createEntityGraph (Employee.class); entityGraph.addAttributeNodes ("név", "telefonok"); Térkép tulajdonságai = új HashMap (); tulajdonságok.put ("javax.persistence.fetchgraph", entitGraph); return em.find (Munkavállaló.osztály, azonosító, tulajdonságok); } 

Ezt láthatjuk entitás grafikonunk két attribútumot tartalmaz: nevet és telefonokat. Tehát, amikor a JPA ezt SQL-re fordítja, kivetíti a kapcsolódó oszlopokat.

5. Adatok betöltése egy ügyleti körbe

Végül egy utolsó megoldást fogunk feltárni. Eddig azt láttuk, hogy a probléma a perzisztencia kontextus életciklusához kapcsolódik.

Az történik a perzisztencia-kontextusunk tranzakciókörű és nyitva marad, amíg a tranzakció befejeződik. A tranzakció életciklusa a repository módszer végrehajtásának elejétől a végéig tart.

Tehát hozzunk létre egy újabb tesztesetet, és állítsuk be a Perzisztencia-kontextust úgy, hogy a teszt módszerünkkel elindított tranzakcióhoz kapcsolódjon. A teszt végéig nyitva tartjuk a perzisztencia-kontextust:

@Test @Transactional public void whenUseTransaction_thenFetchResult () {Alkalmazott alkalmazott = alkalmazottRepository.findById (1); assertThat (alkalmazott.getPhones (). méret (), az (2)); } 

A @ Tranzakció az annotáció egy tranzakciós proxyt konfigurál a kapcsolódó tesztosztály példánya köré. Sőt, a tranzakció társul a végrehajtó szálhoz. Figyelembe véve az alapértelmezett tranzakcióterjesztési beállítást, minden ezzel a módszerrel létrehozott Persistence Context csatlakozik ugyanahhoz a tranzakcióhoz. Következésképpen a tranzakció-perzisztencia összefüggései a vizsgálati módszer tranzakciós hatóköréhez vannak kötve.

6. Következtetés

Ebben az oktatóanyagban három különböző megoldást értékeltünk a lusta társulásoktól származó adatok zárt perzisztencia-kontextusban történő olvasásának problémájának kezelésére.

Először a JPA lekérdezési nyelvet használtuk az elemgyűjtemények lekéréséhez. Ezután meghatároztunk egy entitásdiagramot a szükséges adatok beolvasásához.

És a végső megoldásban a tavaszi tranzakciót használtuk arra, hogy nyitva tartsuk a perzisztencia kontextust, és elolvassuk a szükséges adatokat.

Mint mindig, az oktatóanyag példakódja elérhető a GitHubon.

Java alsó

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT