Spring Data JPA Delete en relaties

1. Overzicht

In deze zelfstudie bekijken we hoe het verwijderen wordt uitgevoerd in Spring Data JPA.

2. Voorbeeldentiteit

Zoals we weten uit de Spring Data JPA-referentiedocumentatie, bieden repository-interfaces ons enige basisondersteuning voor entiteiten.

Als we een entiteit hebben, zoals een Boek:

@Entity openbare klasse Boek {@Id @GeneratedValue privé Lange id; private String-titel; // standaard constructeurs // standaard getters en setters}

Dan kunnen we Spring Data JPA's uitbreiden CrudRepository om ons toegang te geven tot CRUD-operaties op Boek:

@Repository openbare interface BookRepository breidt CrudRepository uit {}

3. Verwijderen uit repository

Onder andere, CrudRepository bevat twee methoden: deleteById en Verwijder alles.

Laten we deze methoden rechtstreeks vanuit ons testen BookRepository:

@RunWith (SpringRunner.class) @SpringBootTest (klassen = {Application.class}) openbare klasse DeleteFromRepositoryUnitTest {@Autowired privé BookRepository-opslagplaats; Boek book1; Boek book2; Lijst boeken; // data-initialisatie @ Test openbare ongeldig wanneerDeleteByIdFromRepository_thenDeletingShouldBeSuccessful () {repository.deleteById (book1.getId ()); assertThat (repository.count ()). isEqualTo (1); } @Test openbare leegte whenDeleteAllFromRepository_thenRepositoryShouldBeEmpty () {repository.deleteAll (); assertThat (repository.count ()). isEqualTo (0); }}

En ook al gebruiken we CrudRepository, merk op dat dezelfde methoden bestaan ​​voor andere Spring Data JPA-interfaces zoals JpaRepository of PagingAndSortingRepository.

4. Afgeleide verwijderquery

We kunnen ook zoekmethoden afleiden voor het verwijderen van entiteiten. Er zijn een aantal regels om ze te schrijven, maar laten we ons concentreren op het eenvoudigste voorbeeld.

Een afgeleide verwijderquery moet beginnen met deleteBy, gevolgd door de naam van de selectiecriteria. Deze criteria moeten worden opgegeven in de methodeaanroep.

Laten we zeggen dat we willen verwijderen Boeks door titel. Als we de naamgevingsconventie gebruiken, zouden we beginnen met deleteBy en lijst titel als onze criteria:

@Repository openbare interface BookRepository breidt CrudRepository uit {long deleteByTitle (String-titel); }

De geretourneerde waarde, van het type lang, geeft aan hoeveel records de methode heeft verwijderd.

Laten we een test schrijven en controleren of deze klopt:

@Test @Transactional public void whenDeleteFromDerivedQuery_thenDeletingShouldBeSuccessful () {lang verwijderdRecords = repository.deleteByTitle ("The Hobbit"); assertThat (verwijderdRecords) .isEqualTo (1); }

Voor het behouden en verwijderen van objecten in JPA is een transactie vereist, daarom zouden we een @Transactional annotatie bij het gebruik van deze afgeleide verwijderquery's, om er zeker van te zijn dat er een transactie wordt uitgevoerd. Dit wordt in detail uitgelegd in de ORM met Spring-documentatie.

5. Aangepaste verwijderquery

De namen van methoden voor afgeleide query's kunnen behoorlijk lang worden en zijn beperkt tot slechts één tabel.

Als we iets complexers nodig hebben, kunnen we een aangepaste query schrijven met @Query en @Wijzigen samen.

Laten we eens kijken naar de equivalente code voor onze afgeleide methode van eerder:

@Modifying @Query ("verwijder uit boek b waar b.title =: titel") ongeldig deleteBooks (@Param ("titel") String-titel);

Nogmaals, we kunnen controleren of het werkt met een eenvoudige test:

@Test @Transactional openbare leegte whenDeleteFromCustomQuery_thenDeletingShouldBeSuccessful () {repository.deleteBooks ("The Hobbit"); assertThat (repository.count ()). isEqualTo (1); }

Beide hierboven gepresenteerde oplossingen zijn vergelijkbaar en bereiken hetzelfde resultaat. Ze pakken echter een iets andere benadering aan.

De @Query methode maakt een enkele JPQL-query op basis van de database. Ter vergelijking: de deleteBy methoden voeren een leesquery uit en verwijderen vervolgens elk van de items een voor een.

6. Verwijderen in relaties

Laten we nu kijken wat er gebeurt als we dat hebben relaties met andere entiteiten.

Stel dat we een Categorie entiteit, die een Een te veel associatie met de Boek entiteit:

@Entity openbare klasse Categorie {@Id @GeneratedValue privé Lange id; private String naam; @OneToMany (mappedBy = "categorie", cascade = CascadeType.ALL, orphanRemoval = true) privélijstboeken; // standaard constructeurs // standaard getters en setters}

De Categorie Opslagplaats kan gewoon een lege interface zijn die zich uitbreidt CrudRepository:

@Repository openbare interface CategoryRepository breidt CrudRepository uit {}

We moeten ook het Boek entiteit om deze associatie weer te geven:

@ManyToOne privé categorie categorie;

Laten we nu twee categorieën toevoegen en deze koppelen aan de boeken die we momenteel hebben. Als we nu proberen de categorieën te verwijderen, worden de boeken ook verwijderd:

@Test openbare leegte whenDeletingCategories_thenBooksShouldAlsoBeDeleted () {categoryRepository.deleteAll (); assertThat (bookRepository.count ()). isEqualTo (0); assertThat (categoryRepository.count ()). isEqualTo (0); }

Dit is echter niet bidirectioneel. Dat betekent dat als we de boeken verwijderen, de categorieën er nog steeds zijn:

@Test openbare leegte whenDeletingBooks_thenCategoriesShouldAlsoBeDeleted () {bookRepository.deleteAll (); assertThat (bookRepository.count ()). isEqualTo (0); assertThat (categoryRepository.count ()). isEqualTo (2); }

We kunnen dit gedrag veranderen door de eigenschappen van de relatie te veranderen, zoals de CascadeType.

7. Conclusie

In dit artikel hebben we gekeken naar verschillende manieren om entiteiten in Spring Data JPA te verwijderen. We hebben gekeken naar de verstrekte verwijderingsmethoden van CrudRepository, evenals onze afgeleide of aangepaste zoekopdrachten met @Query annotatie.

We hebben ook gekeken hoe het verwijderen in relaties gebeurt. Zoals altijd zijn alle codefragmenten die in dit artikel worden genoemd, te vinden op onze GitHub-repository.