Proljetno brisanje podataka JPA i odnosi

1. Pregled

U ovom uputstvu ćemo pogledati kako se briše u Spring Data JPA.

2. Uzorak entiteta

Kao što znamo iz referentne dokumentacije Spring Data JPA, sučelja spremišta pružaju nam osnovnu podršku za entitete.

Ako imamo entitet, poput Knjiga:

@ Entity public class Book {@Id @GeneratedValue private Long id; privatni naslov niza; // standardni konstruktori // standardni getteri i postavljači}

Zatim možemo proširiti Spring Data JPA CrudRepository kako bi nam omogućili pristup CRUD operacijama na Knjiga:

@Repository javno sučelje BookRepository proširuje CrudRepository {}

3. Izbriši iz Spremišta

Između ostalih, CrudRepository sadrži dvije metode: deleteById i izbrisati sve.

Isprobajmo ove metode izravno iz našeg Repozitorij knjiga:

@RunWith (SpringRunner.class) @SpringBootTest (classes = {Application.class}) javna klasa DeleteFromRepositoryUnitTest {@Autowired privatno spremište BookRepository; Knjiga knjiga1; Knjiga knjiga2; Popis knjiga; // inicijalizacija podataka @Test javna praznina whenDeleteByIdFromRepository_thenDeletingShouldBeSuccessful () {repository.deleteById (book1.getId ()); assertThat (repository.count ()). isEqualTo (1); } @Test public void whenDeleteAllFromRepository_thenRepositoryShouldBeEmpty () {repository.deleteAll (); assertThat (repository.count ()). isEqualTo (0); }}

I premda se koristimo CrudRepository, imajte na umu da te iste metode postoje i za druga Spring Data JPA sučelja poput JpaRepository ili PagingAndSortingRepository.

4. Izvedeni upit za brisanje

Također možemo izvesti metode upita za brisanje entiteta. Postoji niz pravila za njihovo pisanje, ali usredotočimo se samo na najjednostavniji primjer.

Izvedeni upit za brisanje mora započeti s deleteBy, nakon čega slijedi naziv kriterija za odabir. Ti se kriteriji moraju navesti u pozivu metode.

Recimo da želimo izbrisati Knjigas by titula. Koristeći konvenciju imenovanja, započeli bismo s deleteBy i popis titula kao naši kriteriji:

@Repository javno sučelje BookRepository proširuje CrudRepository {long deleteByTitle (naslov niza); }

Povratna vrijednost tipa dugo, označava koliko je zapisa metoda obrisana.

Napišimo test i provjerimo je li točan:

@Test @Transactional javna praznina whenDeleteFromDerivedQuery_thenDeletingShouldBeSuccessful () {long deletedRecords = repository.deleteByTitle ("Hobbit"); assertThat (deletedRecords) .isEqualTo (1); }

Trajanje i brisanje objekata u JPA zahtijeva transakciju, zato bismo trebali koristiti @Transational napomena kada koristite ove izvedene upite za brisanje kako biste bili sigurni da je transakcija pokrenuta. To je detaljno objašnjeno u ORM-u s Spring dokumentacijom.

5. Prilagođeni upit za brisanje

Imena metoda za izvedene upite mogu postati prilično dugačka i ograničena su na samo jednu tablicu.

Kada trebamo nešto složenije, možemo napisati prilagođeni upit pomoću @Query i @Modificiranje zajedno.

Provjerimo ekvivalentni kod za izvedenu metodu iz ranije:

@Modifying @Query ("delete from Book b where b.title =: title") void deleteBooks (@Param ("title") Naslov niza);

Opet, jednostavnim testom možemo provjeriti radi li:

@Test @Transactional javna praznina kadaDeleteFromCustomQuery_thenDeletingShouldBeSuccessful () {repository.deleteBooks ("Hobbit"); assertThat (repository.count ()). isEqualTo (1); }

Oba gore predstavljena rješenja su slična i postižu isti rezultat. Međutim, oni imaju malo drugačiji pristup.

The @Query metoda stvara jedan JPQL upit prema bazi podataka. Za usporedbu, deleteBy metode izvršavaju upit za čitanje, a zatim brišu svaku stavku jednu po jednu.

6. Izbriši u odnosima

Pogledajmo sada što će se dogoditi kad imamo odnosi s drugim entitetima.

Pretpostavimo da imamo a Kategorija entitet koji ima OneToMany povezanost s Knjiga entitet:

@Entity javna klasa Kategorija {@Id @GeneratedValue private Long id; privatni naziv niza; @OneToMany (mappedBy = "kategorija", cascade = CascadeType.ALL, orphanRemoval = true) privatne knjige s popisa; // standardni konstruktori // standardni getteri i postavljači}

The Repozitorij kategorija može biti prazno sučelje koje se proteže CrudRepository:

Javno sučelje @Repository CategoryRepository proširuje CrudRepository {}

Također bismo trebali izmijeniti Knjiga entitet koji će odražavati ovu povezanost:

Kategorija privatne kategorije @ManyToOne;

Dodajmo sada dvije kategorije i pridružimo ih knjigama koje trenutno imamo. Ako pokušamo izbrisati kategorije, izbrisat će se i knjige:

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

Međutim, ovo nije dvosmjerno. To znači da ako izbrišemo knjige, kategorije su i dalje tu:

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

To ponašanje možemo promijeniti mijenjanjem svojstava odnosa, poput CascadeType.

7. Zaključak

U ovom smo članku pregledali različite načine brisanja entiteta u Spring Data JPA. Pogledali smo navedene metode brisanja iz CrudRepository, kao i izvedene upite ili one prilagođene pomoću @Query bilješka.

Također smo pogledali kako se brisanje vrši u vezama. Kao i uvijek, svi isječci koda spomenuti u ovom članku mogu se naći na našem GitHub spremištu.


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