Hibernate: lagre, vedvarer, update, merge, saveOrUpdate

Innledning

I denne artikkelen vil vi diskutere forskjellene mellom flere metoder For Økten grensesnitt: lagre, vedvarer, update, merge, saveOrUpdate.

Dette er ikke en introduksjon Til Dvalemodus, og du bør allerede vite det grunnleggende om konfigurasjon, objektrelasjonstilordning og arbeid med enhetsforekomster. For en innledende artikkel Til Hibernate, besøk vår tutorial På Hibernate 4 Med Våren.

Videre lesing:

Slette Objekter Med Dvalemodus

Hurtigveiledning for å slette en enhet i Dvalemodus.
Les mer →

Lagrede Prosedyrer Med Dvalemodus

denne artikkelen diskuterer kort hvordan du kaller store prosedyrer fra Dvalemodus.
Les mer →

En Oversikt over Identifikatorer i Dvalemodus/JPA

Lær hvordan du tilordner enhetsidentifikatorer Med Dvalemodus.
Les mer →

Session as A Persistence Context Implementation

Øktgrensesnittet har flere metoder som til slutt resulterer i lagring av data til databasen: fortsett, lagre, oppdater, slå sammen, lagreorupdate. For å forstå forskjellen mellom disse metodene må vi først diskutere Formålet Med Økten som en utholdenhetskontekst og forskjellen mellom tilstandene i entitetsforekomster i forhold til Økten.

Vi bør også forstå Historien Om Dvalemodus som førte til noen delvis dupliserte API-metoder.

2.1. Managing Entity Instances

Bortsett fra objektrelasjonell kartlegging selv, var Et av problemene Som Hibernate var ment å løse, problemet med å administrere enheter under kjøretid. Begrepet «persistence context» er Hibernates løsning på dette problemet. Persistence-kontekst kan betraktes som en beholder eller en hurtigbuffer på første nivå for alle objektene du lastet inn eller lagret i en database under en økt.

økten er en logisk transaksjon, hvilke grenser er definert av programmets forretningslogikk. Når du arbeider med databasen gjennom en vedvarende kontekst, og alle enhetsforekomster er knyttet til denne konteksten, bør du alltid ha en enkelt forekomst av enhet for hver databasepost som du har samhandlet i løpet av økten med.

i Dvalemodus er utholdenhetskonteksten representert av org.dvalemodus.Økt forekomst. For JPA er det javax.utholdenhet.EntityManager. Når Vi bruker Hibernate som EN jpa-leverandør og opererer via EntityManager-grensesnitt, bryter implementeringen av dette grensesnittet i utgangspunktet det underliggende Øktobjektet. Men Hibernate Session gir et rikere grensesnitt med flere muligheter, så noen ganger er det nyttig å jobbe med Session direkte.

2.2. Stater I Enhetsforekomster

enhver enhetsforekomst i søknaden din vises i en av de tre hovedstatene i forhold Til øktens vedvarende kontekst:

  • denne forekomsten har ingen tilsvarende rader i databasen; det er vanligvis bare et nytt objekt som du har opprettet for å lagre i databasen;
  • vedvarende – denne forekomsten er knyttet til et unikt Øktobjekt; ved å skylle Økten til databasen, er denne enheten garantert å ha en tilsvarende konsistent post i databasen;
  • frittstående — denne forekomsten var en gang knyttet til En Økt (i en vedvarende tilstand), men nå er det ikke; en forekomst går inn i denne tilstanden hvis du kaster den ut fra konteksten, fjerner Eller lukker Økten, eller setter forekomsten gjennom serialisering/deserialiseringsprosess.

Her er et forenklet tilstandsdiagram med kommentarer Til Øktmetoder som gjør at tilstandsovergangene skjer.

2016-07-11_13-38-11

når enhetsforekomsten er i fast tilstand, blir alle endringer du gjør i de tilordnede feltene i denne forekomsten, brukt på de tilsvarende databasepostene og-feltene ved spyling Av Økten. Den vedvarende forekomsten kan betraktes som «online», mens den frittliggende forekomsten har gått» offline » og ikke overvåkes for endringer.

Dette betyr at når du endrer felt i et fast objekt, trenger du ikke å ringe lagre, oppdatere eller noen av disse metodene for å få disse endringene i databasen: alt du trenger er å forplikte transaksjonen, eller spyle eller lukke økten, når du er ferdig med det.

2.3. Samsvar MED Jpa Spesifikasjon

Hibernate var Den mest vellykkede Java ORM implementering. Ikke rart at spesifikasjonen For Java persistence API (JPA) var sterkt påvirket av Hibernate API. Dessverre var det også mange forskjeller: noen store, noen mer subtile.

For å fungere som en implementering av jpa-standarden måtte Hibernate Api-Er revideres. Flere metoder ble lagt Til Øktgrensesnittet for å matche EntityManager-grensesnittet. Disse metodene tjener samme formål som de» originale » metodene, men samsvarer med spesifikasjonen og har dermed noen forskjeller.

Forskjeller Mellom Operasjonene

det er viktig å forstå fra begynnelsen at alle metodene (fortsett, lagre, oppdater, slå sammen, lagre) ikke umiddelbart resulterer i tilsvarende SQL-OPPDATERING eller SETT inn setninger. Den faktiske lagringen av data til databasen skjer ved å begå transaksjonen eller spyle Økten.

de nevnte metodene administrerer i utgangspunktet tilstanden til enhetsinstanser ved å overføre dem mellom forskjellige tilstander langs livssyklusen.

som et eksempel enhet, vil vi bruke en enkel merknad-kartlagt enhet Person:

@Entitypublic class Person { @Id @GeneratedValue private Long id; private String name; // ... getters and setters}

3.1. Persist

persist-metoden er ment for å legge til en ny enhetsforekomst i persistence-konteksten, dvs. å overføre en forekomst fra forbigående til vedvarende tilstand.

vi kaller det vanligvis når vi vil legge til en post i databasen (fortsett en enhetsforekomst):

Person person = new Person();person.setName("John");session.persist(person);

Hva skjer etter at vedvarende metode kalles? Personobjektet har overgått fra forbigående til vedvarende tilstand. Objektet er i utholdenhet sammenheng nå, men ennå ikke lagret i databasen. Genereringen AV INSERT-setninger vil bare skje når du foretar transaksjonen, spyler eller lukker økten.

Legg Merke til at metoden vedvarer har ugyldig returtype. Den opererer på det passerte objektet «på plass», og endrer tilstanden. Personvariabelen refererer til det faktiske vedvarende objektet.

denne metoden er et senere tillegg Til Øktgrensesnittet. Den viktigste differensierende egenskapen ved denne metoden er at DEN er i samsvar MED jsr-220-spesifikasjonen (EJB persistens). Semantikken til denne metoden er strengt definert i spesifikasjonen, som i utgangspunktet sier at:

  • en forbigående forekomst blir vedvarende (og operasjonen kaskader til alle sine relasjoner med cascade=VEDVARER eller cascade=ALL),
  • hvis en forekomst allerede er vedvarende, har dette anropet ingen effekt for denne spesielle forekomsten (men det fortsatt kaskader til sine relasjoner med cascade=VEDVARER eller cascade=ALL),
  • hvis en forekomst er løsrevet, bør du forvente et unntak, enten ved å kalle denne metoden, eller ved å begå eller spyle økten.

Legg Merke til at det ikke er noe her som gjelder identifikatoren for en forekomst. Spesifikasjonen angir ikke at id vil bli generert med en gang, uavhengig av id-genereringsstrategien. Spesifikasjonen for vedvarer metoden tillater gjennomføringen å utstede uttalelser for å generere id på commit eller flush, og id er ikke garantert å være ikke-null etter å kalle denne metoden, så du bør ikke stole på det.

du kan ringe denne metoden på en allerede vedvarende forekomst, og ingenting skjer. Men hvis du prøver å fortsette en frittliggende forekomst, er implementeringen bundet til å kaste et unntak. I følgende eksempel fortsetter vi enheten, kaster den ut fra konteksten slik at den blir løsrevet, og prøver deretter å fortsette igjen. Den andre samtalen til økten.vedvarer () forårsaker et unntak, så følgende kode vil ikke fungere:

Person person = new Person();person.setName("John");session.persist(person);session.evict(person);session.persist(person); // PersistenceException!

3.2. Lagre

lagringsmetoden er en «original» Dvalemodus som ikke samsvarer MED jpa-spesifikasjonen.

dens formål er i utgangspunktet det samme som vedvarer, men det har forskjellige implementeringsdetaljer. Dokumentasjonen for denne metoden sier strengt at den vedvarer forekomsten ,» først tilordne en generert identifikator». Metoden er garantert å returnere Serialiseringsverdien til denne identifikatoren.

Person person = new Person();person.setName("John");Long id = (Long) session.save(person);

effekten av å lagre en allerede vedvarende forekomst er den samme som ved vedvarende. Forskjellen kommer når du prøver å lagre en frittliggende forekomst:

Person person = new Person();person.setName("John");Long id1 = (Long) session.save(person);session.evict(person);Long id2 = (Long) session.save(person);

id2-variabelen vil avvike fra id1. Anropet lagre på en frittstående forekomst oppretter en ny vedvarende forekomst og tildeler den en ny identifikator, som resulterer i en duplikat post i en database ved å begå eller spyle.

3.3. Flett

hovedformålet med flettemetoden er å oppdatere en vedvarende enhetsforekomst med nye feltverdier fra en frittstående enhetsforekomst.

anta for eksempel at du har Et RESTful-grensesnitt med en metode for å hente ET JSON-serialisert objekt ved sin id til den som ringer og en metode som mottar en oppdatert versjon av dette objektet fra den som ringer. En enhet som gikk gjennom en slik serialisering / deserialisering vil vises i en frittstående tilstand.

etter at du har deserialisert denne enhetsforekomsten, må du få en vedvarende enhetsforekomst fra en vedvarende kontekst og oppdatere feltene med nye verdier fra denne frittstående forekomsten. Så fusjonsmetoden gjør akkurat det:

  • finner en enhetsforekomst med id hentet fra det passerte objektet (enten en eksisterende enhetsforekomst fra vedvarende kontekst hentes, eller en ny forekomst lastet fra databasen);
  • kopierer felt fra det overførte objektet til denne forekomsten;
  • returnerer nylig oppdatert forekomst.

i følgende eksempel kan vi kaste ut (løsne) den lagrede enheten fra kontekst, endre navn-feltet og deretter slå sammen den frittstående enheten.

Person person = new Person(); person.setName("John"); session.save(person);session.evict(person);person.setName("Mary");Person mergedPerson = (Person) session.merge(person);

Merk at flettemetoden returnerer et objekt — det er det sammenslåtte personobjektet som ble lastet inn i vedvarende kontekst og oppdatert, ikke personobjektet du passerte som et argument. Det er to forskjellige objekter ,og personobjektet må vanligvis kasseres (uansett, ikke stole på at det er knyttet til utholdenhetskontekst).

som med vedvarende metode, er fusjonsmetoden spesifisert AV JSR-220 for å ha visse semantikk som du kan stole på:

  • hvis enheten er frakoblet, kopieres den til en eksisterende vedvarende enhet;
  • hvis enheten er forbigående, kopieres den til en nyopprettet vedvarende enhet;
  • denne operasjonen kaskader for alle relasjoner med cascade=MERGE eller cascade=ALL tilordning;
  • hvis enheten er vedvarende, har ikke dette metodekallet noen effekt på den (men cascading finner fortsatt sted).

3.4. Update

som med vedvarer og lagre, er oppdateringsmetoden en «original» Dvalemodus som var tilstede lenge før flettemetoden ble lagt til. Dens semantikk er forskjellig på flere viktige punkter:

  • oppdateringsmetoden overfører det passerte objektet fra frittstående til vedvarende tilstand;
  • denne metoden gir et unntak hvis du sender det til en forbigående enhet.

i det følgende eksemplet lagrer vi objektet, og kaster det ut (løsner) fra konteksten, endrer navnet og kaller oppdateringen. Legg merke til at vi ikke legger resultatet av oppdateringsoperasjonen i en egen variabel, fordi oppdateringen finner sted på selve personobjektet. I utgangspunktet kobler vi den eksisterende enhetsinstansen til utholdenhetskonteksten-noe JPA-spesifikasjonen ikke tillater oss å gjøre.

Person person = new Person();person.setName("John");session.save(person);session.evict(person);person.setName("Mary");session.update(person);

Prøver å ringe oppdatering på en forbigående forekomst vil resultere i et unntak. Følgende vil ikke fungere:

Person person = new Person();person.setName("John");session.update(person); // PersistenceException!

3.5. SaveOrUpdate

denne metoden vises bare I Hibernate API og har ikke sin standardiserte motpart. I likhet med oppdatering, kan den også brukes til å koble til forekomster på nytt.

faktisk er den interne DefaultUpdateEventListener-klassen som behandler oppdateringsmetoden En underklasse Av DefaultSaveOrUpdateListener, som bare overstyrer noe funksjonalitet. Hovedforskjellen mellom saveOrUpdate-metoden er at den ikke kaster unntak når den brukes på en forbigående forekomst; i stedet gjør den denne forbigående forekomsten vedvarende. Følgende kode vil fortsette en nyopprettet forekomst Av Person:

Person person = new Person();person.setName("John");session.saveOrUpdate(person);

du kan tenke på denne metoden som et universelt verktøy for å gjøre et objekt vedvarende uavhengig av tilstanden om det er forbigående eller løsrevet.

Hva Skal Du Bruke?

hvis du ikke har noen spesielle krav, som en tommelfingerregel, bør du holde deg til vedvarer og flette metoder, fordi de er standardisert og garantert å samsvare MED jpa spesifikasjonen.

De er også bærbare hvis du bestemmer deg for å bytte til en annen utholdenhetsleverandør, men de kan noen ganger ikke virke så nyttige som De «originale» Dvalemodusene, lagre, oppdatere og lagre.

Konklusjon

Vi har diskutert formålet med Ulike Hibernate-Øktmetoder i forhold til å administrere vedvarende enheter i kjøretid. Vi har lært hvordan disse metodene transist enhet forekomster gjennom sine livssykluser og hvorfor noen av disse metodene har duplisert funksjonalitet.



+