Motstand stater i Hibernate's Session

1. Introduksjon

Dvalemodus er et praktisk rammeverk for å håndtere vedvarende data, men å forstå hvordan det fungerer internt kan til tider være vanskelig.

I denne opplæringen lærer vi om objekttilstander og hvordan man beveger seg mellom dem. Vi vil også se på problemene vi kan støte på frittliggende enheter og hvordan vi kan løse dem.

2. Hibernatesession

De Økt grensesnitt er det viktigste verktøyet som brukes til å kommunisere med dvalemodus. Det gir et API som gjør det mulig for oss å opprette, lese, oppdatere og slette vedvarende objekter. De økt har en enkel livssyklus. Vi åpner den, utfører noen operasjoner, og lukker den deretter.

Når vi opererer på gjenstandene i løpet av økt, de blir knyttet til det økt. Endringene vi gjør oppdages og lagres når de lukkes. Etter lukking bryter dvalemodus forbindelsene mellom objektene og økten.

3. Gjenstandsstater

I sammenheng med dvalemodus Økt, objekter kan være i en av tre mulige tilstander: forbigående, vedvarende eller løsrevet.

3.1. Flyktig

Et objekt vi ikke har festet til noen økt er i forbigående tilstand. Siden den aldri ble vedvarende, har den ingen representasjon i databasen. Fordi nei økt er klar over det, blir det ikke lagret automatisk.

La oss lage et brukerobjekt med konstruktøren og bekrefte at det ikke administreres av økten:

Sessionsøkt = openSession (); UserEntity userEntity = ny UserEntity ("John"); assertThat (session.contains (userEntity)). isFalse ();

3.2. Vedvarende

Et objekt som vi har assosiert med en økt er i vedvarende tilstand. Vi lagret den enten eller leste den fra en utholdenhetskontekst, så den representerer en rad i databasen.

La oss lage et objekt og deretter bruke fortsette metode for å gjøre den vedvarende:

Sessionsøkt = openSession (); UserEntity userEntity = ny UserEntity ("John"); session.persist (userEntity); assertThat (session.contains (userEntity)). isTrue ();

Alternativt kan vi bruke lagre metode. Forskjellen er at fortsette metoden vil bare lagre et objekt, og lagre metoden vil i tillegg generere identifikatoren hvis det er nødvendig.

3.3. Frakoblet

Når vi lukker økt, blir alle gjenstander i den løsrevet. Selv om de fremdeles representerer rader i databasen, administreres de ikke lenger av noen økt:

session.persist (userEntity); session.close (); assertThat (session.isOpen ()). isFalse (); assertThatThrownBy (() -> session.contains (userEntity));

Deretter lærer vi hvordan du lagrer forbigående og frittliggende enheter.

4. Lagre og feste en enhet på nytt

4.1. Lagre en forbigående enhet

La oss opprette en ny enhet og lagre den i databasen. Når vi først konstruerer objektet, vil det være i forbigående tilstand.

Til fortsette vår nye enhet, bruker vi fortsette metode:

UserEntity userEntity = ny UserEntity ("John"); session.persist (userEntity);

Nå oppretter vi et annet objekt med samme identifikator som det første. Dette andre objektet er forbigående fordi det ennå ikke administreres av noen økt, men vi kan ikke gjøre det vedvarende ved hjelp av fortsette metode. Den er allerede representert i databasen, så den er egentlig ikke ny i sammenheng med utholdenhetslaget.

I stedet, vi bruker slå sammen metode for å oppdatere databasen og gjøre objektet vedvarende:

UserEntity onceAgainJohn = ny UserEntity ("John"); session.merge (onceAgainJohn);

4.2. Lagre en frittstående enhet

Hvis vi lukker det forrige øktvil objektene våre være i en løsrevet tilstand. På samme måte som forrige eksempel er de representert i databasen, men de administreres for øyeblikket ikke av noen økt. Vi kan gjøre dem vedvarende igjen ved hjelp av slå sammen metode:

UserEntity userEntity = ny UserEntity ("John"); session.persist (userEntity); session.close (); session.merge (userEntity);

5. Nestede enheter

Ting blir mer kompliserte når vi vurderer nestede enheter. La oss si at brukerenheten vår også vil lagre informasjon om lederen sin:

offentlig klasse UserEntity {@Id privat strengnavn; @ManyToOne privat UserEntity-leder; }

Når vi lagrer denne enheten, må vi ikke bare tenke på tilstanden til selve enheten, men også om tilstanden til den nestede enheten. La oss opprette en vedvarende brukerenhet og deretter angi lederen:

UserEntity userEntity = ny UserEntity ("John"); session.persist (userEntity); UserEntity manager = ny UserEntity ("Adam"); userEntity.setManager (manager);

Hvis vi prøver å oppdatere det nå, får vi et unntak:

assertThatThrownBy (() -> {session.saveOrUpdate (userEntity); transaction.commit ();});
java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: objekt refererer til en ikke-lagret forbigående forekomst - lagre den forbigående forekomsten før du skyller: com.baeldung.states.UserEntity.manager -> com.baeldung.states.UserEntity 

Det skjer fordi dvalemodus ikke vet hva de skal gjøre med den forbigående nestede enheten.

5.1. Vedvarende nestede enheter

En måte å løse dette problemet på er å eksplisitt vedvare nestede enheter:

UserEntity manager = ny UserEntity ("Adam"); session.persist (manager); userEntity.setManager (manager);

Etter at vi har begått transaksjonen, vil vi kunne hente den riktig lagrede enheten:

transaction.commit (); session.close (); Session otherSession = openSession (); UserEntity savedUser = otherSession.get (UserEntity.class, "John"); assertThat (savedUser.getManager (). getName ()). isEqualTo ("Adam");

5.2. Cascading Operations

Forbigående nestede enheter kan vedvares automatisk hvis vi konfigurerer forholdet kaskade eiendom riktig i enhetsklassen:

@ManyToOne (cascade = CascadeType.PERSIST) privat UserEntity manager;

Nå når vi fortsetter objektet, vil denne operasjonen bli kaskadert for alle nestede enheter:

UserEntityWithCascade userEntity = ny UserEntityWithCascade ("John"); session.persist (userEntity); UserEntityWithCascade manager = ny UserEntityWithCascade ("Adam"); userEntity.setManager (manager); // legg til transient manager til vedvarende brukersession.saveOrUpdate (userEntity); transaction.commit (); session.close (); Session otherSession = openSession (); UserEntityWithCascade savedUser = otherSession.get (UserEntityWithCascade.class, "John"); assertThat (savedUser.getManager (). getName ()). isEqualTo ("Adam");

6. Sammendrag

I denne opplæringen tok vi en nærmere titt på hvordan dvalemodus Økt fungerer med hensyn til objekttilstand. Vi inspiserte deretter noen problemer det kan skape og hvordan vi kan løse dem.

Som alltid er kildekoden tilgjengelig på GitHub.


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