Spring Data JPA en Named Entity Graphs

1. Overzicht

Simpel gezegd, Entiteitsgrafieken zijn een andere manier om een ​​query in JPA 2.1 te beschrijven. We kunnen ze gebruiken om beter presterende vragen te formuleren.

In deze zelfstudie leren we aan de hand van een eenvoudig voorbeeld hoe we Entiteitsgrafieken kunnen implementeren met Spring Data JPA.

2. De entiteiten

Laten we eerst een model maken met de naam Item die meerdere kenmerken heeft:

@Entity openbare klasse Item {@Id privé Lange id; private String naam; @OneToMany (mappedBy = "item") karakteristieken van de privélijst = nieuwe ArrayList (); // getters en setters}

Laten we nu de C definiërenharacteristisch entiteit:

@Entity openbare klasse Kenmerk {@Id privé Lange id; privé String-type; @ManyToOne (fetch = FetchType.LAZY) @JoinColumn privéitem; // Getters en Setters}

Zoals we in de code kunnen zien, zijn zowel de kenmerken veld in het Item entiteit en de item veld in het Kenmerkend entiteit worden lui geladen met behulp van de halen parameter. Zo, ons doel hier is om ze tijdens runtime gretig te laden.

3. De entiteitsgrafieken

In Spring Data JPA kunnen we een entiteitsgrafiek definiëren met behulp van een combinatie van @NamedEntityGraph en @EntityGraph annotaties. Of we kunnen ook ad-hoc entiteitsgrafieken definiëren met alleen de attributePaths argument van de @EntityGraph annotatie.

Laten we eens kijken hoe het kan worden gedaan.

3.1. Met @NamedEntityGraph

Ten eerste kunnen we JPA's gebruiken @NamedEntityGraph annotatie rechtstreeks op onze Item entiteit:

@Entity @NamedEntityGraph (name = "Item.characteristics", attributeNodes = @NamedAttributeNode ("kenmerken")) openbare klasse Item {// ...}

En dan kunnen we het @EntityGraph annotatie naar een van onze repository-methoden:

openbare interface ItemRepository breidt JpaRepository {@EntityGraph (value = "Item.characteristics") Item findByName (String naam) uit; }

Zoals de code laat zien, hebben we de naam van de entiteitsgrafiek doorgegeven, die we eerder hebben gemaakt op de Item entiteit, naar de @EntityGraph annotatie. Wanneer we de methode aanroepen, is dat de query die Spring Data zal gebruiken.

De standaardwaarde van het type-argument van het @EntityGraph annotatie is EntityGraphType.FETCH. Wanneer we dit gebruiken, past de Spring Data-module de FetchType.EAGER strategie op de opgegeven kenmerkknooppunten. En voor anderen is de FetchType.LAZY strategie zal worden toegepast.

Dus in ons geval is de kenmerken eigenschap wordt gretig geladen, ook al is de standaard ophaalstrategie van de @Een te veel annotatie is lui.

Een vangst hier is dat als het gedefinieerd halen strategie is EAGER, dan kunnen we zijn gedrag niet veranderen in LUI. Dit is inherent aan het ontwerp, aangezien de volgende bewerkingen de gretig opgehaalde gegevens op een later punt tijdens de uitvoering nodig kunnen hebben.

3.2. Zonder @NamedEntityGraph

Of we kunnen ook een ad-hoc entiteitsgrafiek definiëren, met attributePaths.

Laten we een ad-hoc entiteitsgrafiek toevoegen aan onze Kenmerken Opslagplaats die gretig zijn Item ouder:

openbare interface CharacteristicsRepository breidt JpaRepository {@EntityGraph (attributePaths = {"item"}) Characteristic findByType (String-type) uit; }

Hierdoor wordt het item eigendom van de Kenmerkend entiteit gretig, ook al verklaart onze entiteit een luie-laadstrategie voor deze eigenschap.

Dit is handig omdat we de entiteitsgrafiek inline kunnen definiëren in plaats van te verwijzen naar een bestaande entiteitsgrafiek met een naam.

4. Testgeval

Nu we onze entiteitsgrafieken hebben gedefinieerd, gaan we een testcase maken om deze te verifiëren:

@DataJpaTest @RunWith (SpringRunner.class) @Sql (scripts = "/entitygraph-data.sql") openbare klasse EntityGraphIntegrationTest {@Autowired privé ItemRepository itemRepo; @Autowired private CharacteristicsRepository CharacteristicsRepo; @Test openbare leegte gegevenEntityGraph_whenCalled_shouldRetrunDefinedFields () {Item item = itemRepo.findByName ("Tabel"); assertThat (item.getId ()). isEqualTo (1L); } @Test openbare leegte gegevenAdhocEntityGraph_whenCalled_shouldRetrunDefinedFields () {Karakteristiek kenmerk = kenmerkenRepo.findByType ("Rigid"); assertThat (karakteristiek.getId ()). isEqualTo (1L); }}

De eerste test gebruikt de entiteitsgrafiek die is gedefinieerd met de @NamedEntityGraph annotatie.

Laten we eens kijken naar de SQL die wordt gegenereerd door Hibernate:

selecteer item0_.id als id1_10_0_, characteri1_.id als id1_4_1_, item0_.name als naam2_10_0_, characteri1_.item_id als item_id3_4_1_, characteri1_.type als type2_4_1_, characteri1_.item_id als item_id3_ karakter_i1 kenmerki als item_id3_ buiten id3_4_0_ op item0_.id = characteri1_.item_id waar item0_.name =?

Laten we ter vergelijking de @EntityGraph annotatie uit de repository en inspecteer de query:

selecteer item0_.id als id1_10_, item0_.name als naam2_10_ uit item item0_ waar item0_.name =?

Uit deze vragen kunnen we duidelijk zien dat de vraag is gegenereerd zonder @EntityGraph annotatie laadt geen eigenschappen van Kenmerkend entiteit. Als gevolg hiervan laadt het alleen de Item entiteit.

Laten we ten slotte de Hibernate-query's van de tweede test vergelijken met de @EntityGraph annotatie:

selecteer characteri0_.id als id1_4_0_, item1_.id als id1_10_1_, characteri0_.item_id als item_id3_4_0_, characteri0_.type als type2_4_0_, item1_.name als naam2_10_1_ van kenmerk characteri0_ linker buitenste join item item1_ op character_id.type.type2_4_0_. =?

En de vraag zonder de @EntityGraph annotatie:

selecteer characteri0_.id als id1_4_, characteri0_.item_id als item_id3_4_, characteri0_.type als type2_4_ uit kenmerk characteri0_ waarbij characteri0_.type =?

5. Conclusie

In deze zelfstudie hebben we geleerd hoe u JPA-entiteitsgrafieken in Spring Data kunt gebruiken. Met Spring Data, we kunnen meerdere repository-methoden maken die zijn gekoppeld aan verschillende entiteitsgrafieken.

De voorbeelden voor dit artikel zijn beschikbaar op GitHub.