Tavaszi adatok Közös Parlamenti Közgyűlés előrejelzése

1. Áttekintés

Amikor a Spring Data JPA-t használja a perzisztencia réteg megvalósításához, a lerakat általában a gyökérosztály egy vagy több példányát adja vissza. Gyakran azonban nincs szükségünk a visszaküldött objektumok összes tulajdonságára.

Ilyen esetekben kívánatos lehet az adatok lekérdezése testreszabott típusú objektumokként. Ezek a típusok a gyökérosztály részleges nézeteit tükrözik, csak azokat a tulajdonságokat tartalmazzák, amelyek számunkra fontosak. Itt jönnek jól az előrejelzések.

2. Kezdeti beállítás

Az első lépés a projekt beállítása és az adatbázis feltöltése.

2.1. Maven-függőségek

A függőségekért olvassa el az oktatóanyag 2. szakaszát.

2.2. Entitásosztályok

Határozzunk meg két entitásosztályt:

@Entity public class Cím {@Id private Long id; @OneToOne magánszemély; privát String állam; privát String város; saját vonós utca; privát karakterlánc irányítószám; // szerelők és beállítók}

És:

@Entity public class Person {@Id private Long id; privát karakterlánc keresztnév; privát karakterlánc vezetéknév; @OneToOne (mappedBy = "személy") privát cím címe; // szerelők és beállítók}

A kapcsolat köztük Személy és Cím az entitások kétirányúak: Cím a tulajdonos oldala, és Személy a fordított oldala.

Ebben az oktatóanyagban vegye figyelembe a beágyazott adatbázist - H2.

A beágyazott adatbázis konfigurálásakor a Spring Boot automatikusan generál mögöttes táblákat az általunk meghatározott entitásokhoz.

2.3. SQL parancsfájlok

Használjuk a projection-insert-data.sql szkript mindkét háttértábla feltöltéséhez:

INSERT INTO személy (azonosító, keresztnév, vezetéknév) ÉRTÉKEK (1, 'John', 'Doe'); INSERT INTO address (azonosító, személy_azonosító, állam, város, utca, irányítószám) ÉRTÉKEK (1,1, 'CA', 'Los Angeles', 'Standford Ave', '90001');

Az adatbázis minden tesztfuttatás utáni megtisztításához használhatunk egy másik szkriptet, a nevét projection-clean-up-data.sql:

DELETE FROM cím; TÖRLÉS személytől;

2.4. Teszt osztály

Annak megerősítéséhez, hogy az előrejelzések helyes adatokat szolgáltatnak, szükségünk van egy tesztosztályra:

@DataJpaTest @RunWith (SpringRunner.class) @Sql (scripts = "/projection-insert-data.sql") @Sql (scripts = "/projection-clean-up-data.sql", végrehajtásPhase = AFTER_TEST_METHOD) public class JpaProjectionInt {// injektált mezők és vizsgálati módszerek}

A megadott kommentárokkal A Spring Boot létrehozza az adatbázist, injektálja a függőségeket, és feltölti és tisztítja a táblákat az egyes tesztelési módszerek végrehajtása előtt és után.

3. Interfész alapú vetületek

Entitás kivetítésekor természetes, hogy támaszkodunk egy felületre, mivel nem lesz szükségünk megvalósításra.

3.1. Zárt vetületek

Visszatekintve a Cím osztály, láthatjuk sok tulajdonsága van, mégsem mindegyik hasznos. Például néha egy irányítószám elegendő a cím megjelölésére.

Nyújtsunk be egy vetítési felületet a Cím osztály:

nyilvános felület AddressView {String getZipCode (); }

Ezután használja a tároló felületén:

nyilvános felület Az AddressRepository kiterjeszti a tárat {list getAddressByState (String állapot); }

Könnyen belátható, hogy a repository módszer meghatározása egy vetítési felülettel nagyjából megegyezik egy entitás osztályéval.

Az egyetlen különbség az a vetítési felületet, nem pedig az entitás osztályt, használják elemként a visszaküldött gyűjteményben.

Tegyünk egy gyors tesztet a Cím kivetítés:

@Autowired private AddressRepository addressRepository; @Test public void whenUsingClosedProjections_thenViewWithRequiredPropertiesIsReturned () {AddressView addressView = addressRepository.getAddressByState ("CA"). Get (0); assertThat (addressView.getZipCode ()). isEqualTo ("90001"); // ...}

A színfalak mögött, A Spring minden entitás objektumhoz létrehoz egy proxy példányt a vetítési felületről, és a proxybe irányuló összes hívás továbbításra kerül az adott objektumra.

Rekurzívan használhatjuk a vetületeket. Például itt van egy vetítési felület a Személy osztály:

nyilvános felület PersonView {String getFirstName (); String getLastName (); }

Most adjunk hozzá egy metódust a visszatérés típusával PersonView - beágyazott vetület - a Cím kivetítés:

nyilvános felület AddressView {// ... PersonView getPerson (); }

Vegye figyelembe, hogy a beágyazott vetületet visszaadó metódusnak ugyanazzal a névvel kell rendelkeznie, mint a gyökérosztály metódusának, amely a kapcsolódó entitást adja vissza.

Ellenőrizzük a beágyazott előrejelzéseket néhány utasítás hozzáadásával az imént írt teszt módszerhez:

// ... PersonView personView = addressView.getPerson (); assertThat (personView.getFirstName ()). isEqualTo ("John"); assertThat (personView.getLastName ()). isEqualTo ("Doe");

Vegye figyelembe, hogy rekurzív vetületek csak akkor működnek, ha a tulajdonos oldalról az inverz oldalra haladunk. Ha fordítva tennénk, akkor a beágyazott vetületre állítanánk nulla.

3.2. Nyissa meg a Vetítések lehetőséget

Eddig a pontig zárt vetületeken mentünk keresztül, amelyek olyan vetítési felületeket jeleznek, amelyek metódusai pontosan megegyeznek az entitás tulajdonságainak nevével.

Van még egyfajta interfész-alapú vetítés: nyitott vetületek. Ezek az előrejelzések lehetővé teszik az illesztési módszerek definiálását páratlan nevekkel és futás közben kiszámított visszatérési értékekkel.

Térjünk vissza a Személy vetítési felület és adjon hozzá egy új módszert:

nyilvános felület PersonView {// ... @Value ("# {target.firstName + '' + target.lastName}") Karakterlánc getFullName (); }

Az érv a @Érték az annotáció egy SPEL kifejezés, amelyben a cél a kijelölő a támogató entitás objektumot jelöli.

Most meghatározunk egy másik tároló felületet:

nyilvános felület A PersonRepository kiterjeszti a Repository-t {PersonView findByLastName (String vezetéknév); }

Az egyszerűség kedvéért csak egy vetület objektumot adunk vissza gyűjtemény helyett.

Ez a teszt megerősíti, hogy a nyílt előrejelzések a várt módon működnek:

@Autowired private PersonRepository personRepository; @Testpublic void whenUsingOpenProjections_thenViewWithRequiredPropertiesIsReturned () {PersonView personView = personRepository.findByLastName ("Doe"); assertThat (personView.getFullName ()). isEqualTo ("John Doe"); }

A nyitott előrejelzéseknek van egy hátránya: a Spring Data nem tudja optimalizálni a lekérdezés végrehajtását, mivel nem tudja előre, hogy mely tulajdonságokat fogja használni. Így, csak akkor használjunk nyitott vetületeket, ha a zárt vetületek nem képesek kielégíteni a követelményeinket.

4. Osztályalapú vetületek

A Spring Data a proxyk használata helyett vetítési interfészekből hoz létre nekünk meghatározhatjuk saját vetítési osztályainkat.

Például itt van egy vetítési osztály a Személy entitás:

public class PersonDto {private String keresztnév; privát karakterlánc vezetéknév; public PersonDto (karakterlánc keresztnév, karakterlánc vezetéknév) {this.firstName = keresztnév; this.lastName = vezetékNév; } // getters, egyenlő és hashCode}

Ahhoz, hogy a vetítési osztály egy lerakat interfésszel párhuzamosan működjön, a konstruktora paraméterneveinek meg kell egyezniük a gyökér entitás osztály tulajdonságainak.

Meg kell határoznunk egyenlő és hash kód megvalósítások - ezek lehetővé teszik a Spring Data számára a vetület objektumainak feldolgozását egy gyűjteményben.

Most adjunk hozzá egy metódust a Személy adattár:

nyilvános felület A PersonRepository kiterjeszti a Repository-t {// ... PersonDto findByFirstName (String firstName); }

Ez a teszt ellenőrzi osztályalapú vetületünket:

@Test public void whenUsingClassBasedProjections_thenDtoWithRequiredPropertiesIsReturned () {PersonDto personDto = personRepository.findByFirstName ("John"); assertThat (personDto.getFirstName ()). isEqualTo ("John"); assertThat (personDto.getLastName ()). isEqualTo ("Doe"); }

Az osztályalapú megközelítésnél vegye figyelembe, hogy nem használhatunk beágyazott vetületeket.

5. Dinamikus vetületek

Egy entitásosztálynak sok vetülete lehet. Bizonyos esetekben használhatunk egy bizonyos típust, más esetekben azonban más típusra lehet szükségünk. Néha magának az entitásosztálynak is használnunk kell.

Különálló lerakat-interfészek vagy módszerek meghatározása csak a több visszatérési típus támogatásához nehézkes. Ennek a problémának a kezelésére a Spring Data jobb megoldást kínál: dinamikus előrejelzéseket.

Dinamikus vetületeket csak úgy alkalmazhatunk, ha egy repository metódust deklarálunk az a-val Osztály paraméter:

nyilvános felület A PersonRepository kiterjeszti a Repository {// ... T findByLastName (String vezetéknév, Osztálytípus); }

Ha egy vetítési típust vagy az entitásosztályt átadunk egy ilyen módszernek, lekérhetjük a kívánt típusú objektumot:

@Test public void whenUsingDynamicProjections_thenObjectWithRequiredPropertiesIsReturned () {Person person = personRepository.findByLastName ("Doe", Person.class); PersonView personView = personRepository.findByLastName ("Doe", PersonView.class); PersonDto personDto = personRepository.findByLastName ("Doe", PersonDto.class); assertThat (person.getFirstName ()). isEqualTo ("John"); assertThat (personView.getFirstName ()). isEqualTo ("John"); assertThat (personDto.getFirstName ()). isEqualTo ("John"); }

6. Következtetés

Ebben a cikkben áttekintettük a Spring Data JPA különböző típusú vetületeit.

Az oktatóanyag forráskódja elérhető a GitHubon. Ez egy Maven projekt, és képesnek kell lennie a jelenlegi állapotban történő futtatásra.