hva er forskjellen mellom fortsett, lagre, slå sammen og oppdater? Hvilken skal du bruke?

Jpa og Hibernate gir forskjellige metoder for å fortsette nye og oppdatere eksisterende enheter. DU kan velge MELLOM JPA er vedvarer og flette Og Hibernate er lagre og oppdatere metoder.

det virker som om det er 2 par med 2 metoder som gjør det samme. Du kan bruke metodene vedvarer og lagres til å lagre en ny enhet, og metodene flettes og oppdateres til å lagre endringene i en frittstående enhet i databasen. Det er derfor mange utviklere lurer på hvilken av disse metodene de skal bruke. La oss ta en nærmere titt på detaljene og små forskjeller i disse metodene.

Spesiell takk Til Steve Ebersole (Lead Developer – Hibernate ORM) som ga sin tilbakemelding og god innsikt i Noen Av Hibernates skjulte implementeringsdetaljer!

Entity State Transitions

Før vi kommer inn i detaljene i disse 4 metodene, må jeg gi deg en rask introduksjon til JPAS entity lifecycle states.

hvis en enhet er knyttet til gjeldende vedvarende kontekst, har den livssyklustilstanden administrert. Det betyr at den er tilordnet til en databasepost. Utholdenhetsleverandøren genererer DE NØDVENDIGE SQL INSERT OG UPDATE-setningene for å overføre alle endringer. En administrert enhet lagres også i hurtigbufferen på 1. nivå.

når du oppretter en ny enhet, er den i forbigående tilstand. Den forblir i denne tilstanden til du knytter den til gjeldende vedvarende kontekst. Jeg vil vise deg hvordan du kan gjøre det med JPA ‘s persist and Hibernate’ s save method, i følgende avsnitt. Så lenge en enhet er i forbigående tilstand, tilordnes den ikke til en databasepost og administreres ikke av en vedvarende kontekst.

Enheter i den frittliggende livssyklustilstanden administreres ikke lenger av persistence-konteksten. Det kan være tilfelle fordi du lukket vedvarende kontekst eller du eksplisitt løsrevet enheten fra gjeldende kontekst. Jeg vil komme inn på flere detaljer om hvordan du kan feste disse enhetene med JPA ‘s merge and Hibernate’ s update methods i en senere del av dette innlegget.

og den siste livssyklustilstanden er fjernet. Disse enhetene var tidligere i staten administrert, før du planla dem for fjerning. Fjerne enheter er utenfor omfanget av dette innlegget, så jeg vil ikke komme inn for mange detaljer om det. Du kan planlegge en enhet for fjerning ved å kalle fjern-metoden på EntityManager-grensesnittet.

Vedvarende En Ny Enhet Ved hjelp av vedvarer eller lagre

når du oppretter et nytt enhetsobjekt, er det i forbigående livssyklustilstand. Det kartlegger ikke noen databasepost.

Author a = new Author();a.setFirstName("Thorben");a.setLastName("Janssen");

du må knytte enheten til en vedvarende kontekst slik at den blir administrert og blir vedvarende i databasen. Du kan enten bruke JPAS vedvarer Eller Hibernate s lagre metode for å gjøre det. Begge metodene ser ut til å gjøre det samme, men det er noen forskjeller.

Spesifikasjon vs. Proprietær API

den mest åpenbare forskjellen er AT jpa-spesifikasjonen definerer persist-metoden. Du kan bruke den med ALLE jpa implementeringer. Lagringsmetoden er Derimot Hibernate-spesifikk. Det er derfor ikke tilgjengelig i andre jpa-implementeringer.

Men det er bare relevant hvis du vil kunne erstatte Dvalemodus med en ANNEN jpa-implementering, som Eclipse Link eller OpenJPA.

Returtyper Og Utførelse AV SQL-Setninger

En annen åpenbar forskjell mellom disse 2 metodene er deres returtype. JPA vedvarer metoden returnerer ugyldig Og Dvalemodus lagre metoden returnerer primærnøkkelen for enheten.

Det kan virke som en stor forskjell, spesielt når du ser nærmere På Hibernates Javadoc og jpa-spesifikasjonen:

  • Javadoc Av Hibernates lagringsmetode sier at den genererer primærnøkkelverdien først:

    Fortsett den gitte forbigående forekomsten, først tilordne en generert identifikator.
    Javadoc-Sesjon.lagre (enhet)

  • du finner ingen informasjon om DETTE i jpa-spesifikasjonen. Det definerer ikke når primærnøkkelverdien må tilordnes. Så, utholdenhet leverandøren kan gjøre det når som helst mellom samtalen av vedvarer metoden og flush av utholdenhet sammenheng.

I de fleste tilfeller gjør det ingen forskjell hvis du ringer til lagre-eller vedvarer-metoden. Dvalemodus bruker navnet på enhetsklassen og primærnøkkelverdien til å lagre enheten i hurtigbufferen på første nivå. Den trenger derfor en primærnøkkelverdi når den utfører vedvarende metode.

I nesten alle situasjoner Genererer Dvalemodus primærnøkkelverdien umiddelbart og utløser EN SQL-setning om nødvendig, når du kaller metoden vedvarer eller lagrer.

men det er ikke tilfelle hvis DU bruker IDENTITETSSTRATEGIEN og prøver å fortsette en enhet uten en aktiv transaksjon eller Med FlushMode.MANUELL. Hvis du kaller metoden vedvarer i en av disse situasjonene, Forsinker Dvalemodus utførelsen AV SQL INSERT-setningen og oppretter en midlertidig primærnøkkelverdi. Men hvis du kaller lagringsmetoden, Utfører Hibernate SQL INSERT-setningen umiddelbart og henter primærnøkkelverdien fra databasen.

du kan deretter hente den som returverdien for lagringsmetoden.

Author a = new Author();a.setFirstName("Thorben");a.setLastName("Janssen");Long id = (Long) em.unwrap(Session.class).save(a);

Eller du kan ringe getter-metoden for primærnøkkelattributtet for den administrerte enheten hvis DU bruker JPAS vedvarende metode.

Author a = new Author();a.setFirstName("Torben");a.setLastName("Janssen");em.persist(a);Long id = a.getId();

Dvalemodus utfører de samme SQL-setningene når du kaller metoden vedvarer eller lagre. Hvilken og når det gjør det, avhenger av din primære nøkkelgenereringsstrategi:

ikke generert

hvis du angir primærnøkkelverdien programmatisk, for eksempel til en naturlig identifikator, Utfører Hibernate bare EN SQL INSERT-setning når den tømmer persistence-konteksten.

14:08:34,979 INFO TestPersistSaveMerge:237 - Save entity14:08:35,052 INFO TestPersistSaveMerge:240 - Commit transaction14:08:35,123 DEBUG SQL:92 - insert into Author (firstName, lastName, version, id) values (?, ?, ?, ?)
YouTube video

Generert MED IDENTITY strategy

Hvis DU bruker IDENTITY strategy til å generere primærnøkkelverdien, Må Dvalemodus utføre INSERT-setningen når du kaller metoden lagre eller vedvarer for å hente primærnøkkelverdien fra databasen.

14:09:28,264 INFO TestPersistSaveMerge:237 - Save entity14:09:28,336 DEBUG SQL:92 - insert into Author (firstName, lastName, version) values (?, ?, ?)14:09:28,354 INFO TestPersistSaveMerge:240 - Commit transaction
YouTube video

Generert MED SEKVENSSTRATEGI

og hvis DU bruker SEKVENSEN, Utfører Hibernate EN SQL SELECT-setning for å hente neste verdi fra databasesekvensen. Dvalemodus forsinker DERETTER INSERT-setningen til den spyler utholdenhetskonteksten. I dette eksemplet skjer flush når transaksjonen blir begått.

14:10:27,994 INFO TestPersistSaveMerge:237 - Save entity14:10:28,002 DEBUG SQL:92 - select nextval ('hibernate_sequence')14:10:28,042 INFO TestPersistSaveMerge:240 - Commit transaction14:10:28,096 DEBUG SQL:92 - insert into Author (firstName, lastName, version, id) values (?, ?, ?, ?)

Generert MED TABELLSTRATEGI

DU bør ikke bruke TABELLSTRATEGIEN fordi den krever radnivålåser på primærnøkkeltabellen og ikke skaleres godt. Hvis Du bruker denne strategien uansett, Utfører Hibernate EN SQL SELECT-setning for å hente neste primærnøkkelverdi fra databasen og skriver den nye verdien til databasetabellen. Det forsinker utførelsen AV SQL INSERT-setningen for den nye enheten til den tømmer persistence-konteksten.

14:11:17,368 INFO TestPersistSaveMerge:237 - Save entity14:11:17,482 DEBUG SQL:92 - select tbl.next_val from hibernate_sequences tbl where tbl.sequence_name=? for update of tbl14:11:17,531 DEBUG SQL:92 - insert into hibernate_sequences (sequence_name, next_val) values (?,?)14:11:17,534 DEBUG SQL:92 - update hibernate_sequences set next_val=? where next_val=? and sequence_name=?14:11:17,584 INFO TestPersistSaveMerge:240 - Commit transaction14:11:17,655 DEBUG SQL:92 - insert into Author (firstName, lastName, version, id) values (?, ?, ?, ?)

Hvilken du skal velge?

du kan forvente at save and persist-metoden oppfører seg annerledes fordi DET er noen forskjeller MELLOM jpa-spesifikasjonen og Javadoc Av Hibernates proprietære metoder.

men nesten alle disse forskjellene forsvinner når du ser på den interne implementeringen. De eneste som gjenstår er 2 hjørnesaker der Dvalemodus kan forsinke henting av primærnøkkelen, returtypen til metoden og støtten fra andre jpa-implementeringer.

for de fleste applikasjoner gjør det ingen forskjell hvis du får den genererte primærnøkkelverdien som returtype Dvalemodus save method eller fra getter-metoden til primærnøkkelattributtet. Så lenge du ikke bruker en utvidet persistence-kontekst og utfører alle databaseoperasjoner med en aktiv transaksjon, anbefaler jeg at DU bruker JPAS vedvarende metode.

Oppdatere en frittstående enhet

når du lukker gjeldende vedvarende kontekst eller eksplisitt fjerner en enhet fra den ved å kalle metodene fjern eller koble fra på EntityManager-grensesnittet, blir enheten frakoblet. Det betyr at Det ikke lenger er lagret i 1. nivå cache og At Dvalemodus ikke vil gjenskape noen av de anvendte endringene i databasen.

Du kan bruke Hibernates oppdatering eller JPAS flettemetode til å knytte en frittstående enhet til en vedvarende kontekst. Når Du har gjort Det, Vil Hibernate oppdatere databasen basert på enhetsattributtverdiene.

effekten av oppdaterings-og fusjonsmetoden ser ut til å være den samme, men som du vil se i de følgende avsnittene, er det en viktig forskjell.

JPAS flettemetode

JPAS flettemetode kopierer tilstanden til en frittstående enhet til en administrert forekomst av samme enhet. Hibernate utfører derfor EN SQL SELECT-setning for å hente en administrert enhet fra databasen. Hvis vedvarende kontekst allerede inneholdt en administrert forekomst av enheten, Bruker Dvalemodus den eksisterende i stedet. Den kopierer deretter alle attributtverdier til den administrerte enheten og returnerer den til den som ringer.

Author managedAuthor = em.merge(a);

etter aktivering av logging AV SQL-setninger, kan du se de utførte SELECT and UPDATE-setningene i loggutgangen.

11:37:21,172 DEBUG SQL:92 - select books0_.bookId as bookId1_2_0_, books0_.authorId as authorId2_2_0_, book1_.id as id1_1_1_, book1_.fk_author as fk_autho6_1_1_, book1_.format as format2_1_1_, book1_.publishingDate as publishi3_1_1_, book1_.title as title4_1_1_, book1_.version as version5_1_1_, author2_.id as id1_0_2_, author2_.firstName as firstNam2_0_2_, author2_.lastName as lastName3_0_2_, author2_.version as version4_0_2_ from BookAuthor books0_ inner join Book book1_ on books0_.authorId=book1_.id left outer join Author author2_ on book1_.fk_author=author2_.id where books0_.bookId=?11:37:21,180 INFO TestPersistSaveMerge:82 - Before commit11:37:21,182 DEBUG SQL:92 - update Author set firstName=?, lastName=?, version=? where id=? and version=?

Når Dvalemodus tømmer utholdenhetskonteksten for neste gang, kontrollerer den skitne kontrollmekanismen alle administrerte enheter. Hvis det oppdager at fletteoperasjonen endret en enhet attributtverdi, utløser den nødvendige SQL UPDATE-setningen.

det er en viktig detalj du trenger å vite når DU bruker JPAS flettemetode. Dvalemodus kopierer attributtverdiene til den frittstående enheten til den administrerte enheten. Dette overskriver eventuelle endringer du har utført på denne enheten i Den gjeldende Økten.

Hibernates oppdateringsmetode

Hibernates oppdateringsmetode utløser ikke EN SQL SELECT-setning. Det legger bare enheten til den nåværende utholdenhetskonteksten. I motsetning TIL JPAS flettemetode, kan du ikke miste noen endringer ved å ringe oppdateringsmetoden. Hvis vedvarende kontekst allerede inneholder en administrert forekomst av enheten du vil oppdatere, kaster den et unntak.

em.unwrap(Session.class).update(a);

Når Dvalemodus utfører neste flush, utfører Den ikke noen skitne sjekker. Det er ikke mulig fordi Hibernate ikke leste den nyeste versjonen av enheten fra databasen. Den utfører bare EN SQL UPDATE-setning for den reattached enheten.

11:38:28,151 INFO TestPersistSaveMerge:121 - Before commit11:38:28,153 DEBUG SQL:92 - update Author set firstName=?, lastName=?, version=? where id=? and version=?

den manglende skitne kontrollen forårsaker en unødvendig SQL UPDATE-setning når enheten og den tilsvarende databaseposten inneholder de samme verdiene. Dette kan være et problem hvis DBA registrerte en oppdateringsutløser for databasetabellen. I slike situasjoner kan du kommentere enheten med @SelectBeforeUpdate.

@Entity@SelectBeforeUpdatepublic class Author { ... }

Som forteller Hibernate å velge enheten og utføre en skitten sjekk før den genererer SQL UPDATE-setningen. Som du kan se i loggutgangen, er oppførselen til oppdateringsmetoden nå lik JPAS flettemetode.

19:08:16,530 INFO TestPersistSaveMerge:121 - Before commit19:08:16,531 DEBUG SQL:92 - select author_.id, author_.firstName as firstNam2_0_, author_.lastName as lastName3_0_, author_.version as version4_0_ from Author author_ where author_.id=?19:08:16,592 DEBUG SQL:92 - update Author set firstName=?, lastName=?, version=? where id=? and version=?

Men det er en signifikant forskjell mellom de 2 metodene. Når du kaller oppdateringsmetoden, Vil Dvalemodus bare velge enheten du oppgav som en metodeparameter. Men når DU kaller JPAS flettemetode, Vil Hibernate også velge alle foreninger Med CascadeType.FLETTE. Du bør derfor foretrekke JPAS flettemetode hvis du legger til en stor graf av enheter på nytt.

Hvilken du skal velge?

det er ikke noe generelt svar på disse spørsmålene. Som du har sett, har begge metodene sine fordeler og ulemper. Du må bestemme for ditt spesifikke brukstilfelle hvis Dvalemodus må velge enheten før DEN utløser SQL UPDATE-setningen. Og hvis det er tilfelle, må du også vurdere dybden av enheten grafen og resultatene implikasjonene av den angitte henting atferd.

Oppdatering av en administrert enhet

JPA og Dvalemodus gjør det svært enkelt å oppdatere en administrert enhet. Hvis enheten din er i livssyklustilstanden administrert, for eksempel fordi du hentet den med EN jpql-spørring eller finn-metoden For EntityManager, trenger du bare å endre verdiene for enhetens attributter.

em = emf.createEntityManager();em.getTransaction().begin();a = em.find(Author.class, a.getId());a.setFirstName("Thorben");log.info("Before commit");em.getTransaction().commit();em.close();

Når Dvalemodus bestemmer seg for å spyle persistence-konteksten, vil den skitne kontrollmekanismen oppdage endringen og utføre DEN nødvendige SQL UPDATE-setningen.

11:41:49,178 DEBUG SQL:92 - select author0_.id as id1_0_0_, author0_.firstName as firstNam2_0_0_, author0_.lastName as lastName3_0_0_, author0_.version as version4_0_0_ from Author author0_ where author0_.id=?11:41:49,191 INFO TestPersistSaveMerge:335 - Before commit11:41:49,193 DEBUG SQL:92 - update Author set firstName=?, lastName=?, version=? where id=? and version=?

du trenger ikke, og du bør ikke ringe Hibernates lagringsmetode etter at du har oppdatert en enhet. Som utløser en ekstra SaveOrUpdate hendelse uten å gi noen fordeler. Når Dvalemodus bestemmer seg for å skylle persistenskonteksten, vil den utføre den skitne kontrollen uansett for å oppdage alle endringer før den utfører DE nødvendige SQL UPDATE-setningene.

You might also like

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.