Slette objekter i dvale

1. Oversikt

Som et fullverdig ORM-rammeverk er Hibernate ansvarlig for livssyklusadministrasjon av vedvarende objekter (enheter), inkludert CRUD-operasjoner som lese, lagre, Oppdater og slett.

I denne artikkelen utforsker vi forskjellige måter objekter kan slettes fra en database ved hjelp av dvalemodus og vi forklarer vanlige problemer og fallgruver som kan oppstå.

Vi bruker JPA og går bare tilbake og bruker Hibernate native API for de funksjonene som ikke er standardisert i JPA.

2. Ulike måter å slette objekter på

Objekter kan slettes i følgende scenarier:

  • Ved bruk av EntityManager. Fjern
  • Når en sletting kaskades fra andre forekomster av enheter
  • Når en foreldreløs fjerning blir brukt
  • Ved å utføre en slett JPQL-uttalelse
  • Ved å utføre innfødte spørsmål
  • Ved å bruke en myk slettingsteknikk (filtrering av myke slettede enheter etter en tilstand i en @Hvor klausul)

I resten av artikkelen ser vi på disse punktene i detalj.

3. Sletting ved hjelp av Entity Manager

Sletting med EntityManager er den enkleste måten å fjerne en enhetsforekomst på:

Foo foo = ny Foo ("foo"); entityManager.persist (foo); flushAndClear (); foo = entityManager.find (Foo.class, foo.getId ()); assertThat (foo, notNullValue ()); entityManager.remove (foo); flushAndClear (); assertThat (entityManager.find (Foo.class, foo.getId ()), nullValue ()); 

I eksemplene i denne artikkelen bruker vi en hjelpermetode for å tømme og rydde utholdenhetskonteksten når det er nødvendig:

ugyldig flushAndClear () {entityManager.flush (); entityManager.clear (); }

Etter å ha ringt EntityManager. Fjern metoden, overføres den medfølgende forekomsten til fjernet status og tilhørende sletting fra databasen skjer ved neste spyling.

Noter det slettet forekomst gjenopprettes hvis en FORTSETTE operasjonen blir brukt på den. En vanlig feil er å ignorere det a FORTSETTE operasjonen har blitt brukt på en fjernet forekomst (vanligvis fordi den kaskades fra en annen forekomst på skylletiden), fordi seksjonen 3.2.2 av JPA-spesifikasjonen pålegger at en slik forekomst skal vedvares igjen i et slikt tilfelle.

Vi illustrerer dette ved å definere a @ManyToOne forening fra Foo til Bar:

@Entity offentlig klasse Foo {@ManyToOne (fetch = FetchType.LAZY, cascade = CascadeType.ALL) privat barbar; // andre kartlegginger, getters og setters}

Når vi sletter en Bar forekomst referert til av en Foo forekomst som også er lastet i vedvarende sammenheng, Bar forekomst vil ikke bli fjernet fra databasen:

Bar bar = new Bar ("bar"); Foo foo = ny Foo ("foo"); foo.setBar (bar); entityManager.persist (foo); flushAndClear (); foo = entityManager.find (Foo.class, foo.getId ()); bar = entityManager.find (Bar.class, bar.getId ()); entityManager.remove (bar); flushAndClear (); bar = entityManager.find (Bar.class, bar.getId ()); assertThat (bar, notNullValue ()); foo = entityManager.find (Foo.class, foo.getId ()); foo.setBar (null); entityManager.remove (bar); flushAndClear (); assertThat (entityManager.find (Bar.class, bar.getId ()), nullValue ());

Hvis den fjernes Bar refereres til av en Foo, den FORTSETTE operasjonen er kaskadert fra Foo til Bar fordi foreningen er merket med cascade = CascadeType.ALL og slettingen er ikke planlagt. For å bekrefte at dette skjer, kan vi aktivere sporingsloggnivå for org. dvale pakke og søk etter oppføringer som fjerning av planlegging av enhetssletting.

4. Cascaded Sletting

Slette kan overføres til barnenheter når foreldrene blir fjernet:

Bar bar = new Bar ("bar"); Foo foo = ny Foo ("foo"); foo.setBar (bar); entityManager.persist (foo); flushAndClear (); foo = entityManager.find (Foo.class, foo.getId ()); entityManager.remove (foo); flushAndClear (); assertThat (entityManager.find (Foo.class, foo.getId ()), nullValue ()); assertThat (entityManager.find (Bar.class, bar.getId ()), nullValue ());

Her bar fjernes fordi fjerning er kaskadert fra foo, ettersom foreningen erklæres å kaskade alle livssyklusoperasjoner fra Foo til Bar.

Noter det det er nesten alltid en feil å kaskade FJERNE drift i en @ManyToMany assosiasjon, fordi det ville utløse fjerning av barneforekomster som kan være knyttet til andre foreldreforekomster. Dette gjelder også for CascadeType.ALL, da det betyr at alle operasjoner skal kaskades, inkludert FJERNE operasjon.

5. Fjerning av foreldreløse barn

De foreldreløs fjerning direktivet erklærer at tilknyttede enhetsforekomster skal fjernes når de skilles fra foreldrene, eller tilsvarende når foreldrene fjernes.

Vi viser dette ved å definere en slik forening fra Bar til Baz:

@Entity public class Bar {@OneToMany (cascade = CascadeType.ALL, orphanRemoval = true) private List bazList = new ArrayList (); // andre kartlegginger, getters og setters}

Deretter en Baz forekomst slettes automatisk når den fjernes fra listen over foreldrene Bar forekomst:

Bar bar = new Bar ("bar"); Baz baz = ny Baz ("baz"); bar.getBazList (). legg til (baz); entityManager.persist (bar); flushAndClear (); bar = entityManager.find (Bar.class, bar.getId ()); baz = bar.getBazList (). get (0); bar.getBazList (). fjerne (baz); flushAndClear (); assertThat (entityManager.find (Baz.class, baz.getId ()), nullValue ());

Semantikken til foreldreløs fjerning operasjonen er helt lik en FJERNE operasjonen brukes direkte på de berørte barneinstansene, som betyr at FJERNE operasjonen kaskades videre til nestede barn. Som en konsekvens må du sørge for at ingen andre tilfeller refererer til de fjernede (ellers gjenopprettes de).

6. Sletting ved hjelp av en JPQL-uttalelse

Dvalemodus støtter DML-slettingsoperasjoner:

Foo foo = ny Foo ("foo"); entityManager.persist (foo); flushAndClear (); entityManager.createQuery ("slett fra Foo hvor id =: id") .setParameter ("id", foo.getId ()) .executeUpdate (); assertThat (entityManager.find (Foo.class, foo.getId ()), nullValue ());

Det er viktig å merke seg det JPQL-setninger i DML-stil påvirker verken tilstanden eller livssyklusen til enhetsforekomster som allerede er lastet inn i utholdenhetskonteksten, så det anbefales at de kjøres før de berørte enhetene lastes inn.

7. Sletting ved hjelp av innfødte spørsmål

Noen ganger må vi falle tilbake til innfødte spørsmål for å oppnå noe som ikke støttes av dvalemodus eller som er spesifikt for en databaseleverandør. Vi kan også slette data i databasen med innfødte spørsmål:

Foo foo = ny Foo ("foo"); entityManager.persist (foo); flushAndClear (); entityManager.createNativeQuery ("slett fra FOO hvor ID =: id") .setParameter ("id", foo.getId ()) .executeUpdate (); assertThat (entityManager.find (Foo.class, foo.getId ()), nullValue ());

Den samme anbefalingen gjelder innfødte spørsmål som for uttalelser i JPA DML-stil, dvs. innfødte spørsmål påvirker verken tilstanden eller livssyklusen til enhetsforekomster som er lastet inn i utholdenhetskonteksten før utførelsen av spørringene.

8. Myk sletting

Ofte er det ikke ønskelig å fjerne data fra en database på grunn av revisjonsformål og historikk. I slike situasjoner kan vi bruke en teknikk som kalles soft deletes. I utgangspunktet merker vi bare en rad som fjernet, og vi filtrerer den ut når vi henter data.

For å unngå mange overflødige forhold i hvor klausuler i alle spørsmålene som leser enheter som er slettbare, gir dvalemodus @Hvor kommentar som kan plasseres på en enhet og som inneholder et SQL-fragment som automatisk legges til SQL-spørringer generert for den enheten.

For å demonstrere dette legger vi til @Hvor kommentar og en kolonne med navnet SLETTET til Foo enhet:

@Entity @Where (clause = "DELETED = 0") offentlig klasse Foo {// andre kartlegginger @Column (name = "SLETTET") privat Heltall slettet = 0; // getters and setters public void setDeleted () {this.deleted = 1; }}

Følgende test bekrefter at alt fungerer som forventet:

Foo foo = ny Foo ("foo"); entityManager.persist (foo); flushAndClear (); foo = entityManager.find (Foo.class, foo.getId ()); foo.setDeleted (); flushAndClear (); assertThat (entityManager.find (Foo.class, foo.getId ()), nullValue ());

9. Konklusjon

I denne artikkelen så vi på forskjellige måter som data kan slettes med dvalemodus. Vi forklarte grunnleggende konsepter og noen gode fremgangsmåter. Vi demonstrerte også hvordan soft-slettinger enkelt kan implementeres med dvalemodus.

Implementeringen av denne slettingen av objekter med dvalemodus er tilgjengelig på Github. Dette er et Maven-basert prosjekt, så det skal være enkelt å importere og kjøre som det er.


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