Hibernácia: ukladanie, pretrvávanie, aktualizácia, zlúčenie, saveOrUpdate

1. Úvod

V tomto článku sa budeme zaoberať rozdielmi medzi niekoľkými metódami Session rozhranie: uložiť, pretrvávať, aktualizovať, zlúčiť, saveOrUpdate.

Toto nie je úvod do režimu dlhodobého spánku a mali by ste už poznať základy konfigurácie, objektovo-relačné mapovanie a prácu s inštanciami entít. Úvodný článok o režime dlhodobého spánku nájdete v našom výučbe o režime dlhodobého spánku s programom Spring.

2. Relácia ako implementácia kontextu perzistencie

The Session rozhranie má niekoľko metód, ktoré nakoniec vyústia do uloženia údajov do databázy: pretrvávať, uložiť, aktualizovať, zlúčiť, saveOrUpdate. Aby sme pochopili rozdiel medzi týmito metódami, musíme najskôr diskutovať o účele Session ako kontext vytrvalosti a rozdiel medzi stavmi inštančných inštancií vo vzťahu k Session.

Mali by sme tiež pochopiť históriu vývoja režimu dlhodobého spánku, ktorá viedla k niektorým čiastočne duplikovaným metódam API.

2.1. Správa inštančných entít

Okrem samotného objektovo-relačného mapovania je jedným z problémov, ktoré mal Hibernate vyriešiť, problém riadenia entít počas behu programu. Pojem „kontext vytrvalosti“ je riešením tohto problému zo strany Hibernate. Kontext vytrvalosti možno považovať za kontajner alebo vyrovnávaciu pamäť prvej úrovne pre všetky objekty, ktoré ste načítali alebo uložili do databázy počas relácie.

Relácia je logická transakcia, ktorej hranice sú definované obchodnou logikou vašej aplikácie. Keď pracujete s databázou v rámci perzistencie a všetky vaše inštančné entity sú pripojené k tomuto kontextu, mali by ste mať vždy jednu inštanciu entity pre každý záznam databázy, s ktorým ste počas relácie interagovali.

V režime dlhodobého spánku predstavuje kontext perzistencie org.hibernate.Session inštancia. Pre JPA je to javax.persistence.EntityManager. Keď používame Hibernate ako poskytovateľa JPA a fungujeme cez EntityManager rozhranie, implementácia tohto rozhrania v podstate obaluje základné Session objekt. Avšak prezimujte Session poskytuje bohatšie rozhranie s viacerými možnosťami, takže niekedy je užitočné s ním pracovať Zasadnutie priamo.

2.2. Štáty inštancií

Akákoľvek inštancia entity vo vašej aplikácii sa nachádza v jednom z troch hlavných stavov vo vzťahu k Session kontext vytrvalosti:

  • prechodný - tento prípad nie je a nikdy nebol pripojený k a Session; táto inštancia nemá v databáze žiadne zodpovedajúce riadky; je to zvyčajne iba nový objekt, ktorý ste vytvorili na uloženie do databázy;
  • vytrvalý - táto inštancia je spojená s jedinečným Session predmet; po prepláchnutí Session do databázy je zaručené, že tento subjekt bude mať v databáze zodpovedajúci konzistentný záznam;
  • oddelený - táto inštancia bola kedysi pripojená k a Session (v vytrvalý štát), ale teraz to tak nie je; inštancia vstúpi do tohto stavu, ak ju vylúčite z kontextu, zrušíte alebo zatvoríte reláciu alebo uvediete inštanciu prostredníctvom procesu serializácie / deserializácie.

Tu je zjednodušený stavový diagram s komentármi k Session metódy, ktoré umožňujú prechod štátu.

Keď je inštancia entity v vytrvalý stave, všetky zmeny, ktoré urobíte v mapovaných poliach tejto inštancie, sa použijú na zodpovedajúce databázové záznamy a polia po vyprázdnení Session. The vytrvalý inštanciu možno považovať za „online“, zatiaľ čo oddelený inštancia prešla do režimu offline a nie je sledovaná kvôli zmenám.

To znamená, že keď zmeníte polia a vytrvalý objekt, nemusíte volať uložiť, aktualizovať alebo ktorákoľvek z týchto metód na získanie týchto zmien v databáze: všetko, čo potrebujete, je vykonať transakciu alebo prepláchnuť alebo ukončiť reláciu, keď ste hotoví.

2.3. Zhoda so špecifikáciou JPA

Hibernate bola najúspešnejšia implementácia Java ORM. Niet divu, že špecifikácia rozhrania JAP (Java persistence API) bola výrazne ovplyvnená rozhraním Hibernate API. Nanešťastie bolo aj veľa rozdielov: niektoré zásadné, iné jemnejšie.

Aby bolo možné implementovať štandard JPA, bolo potrebné revidovať rozhrania Hibernate API. Do rozhrania Session bolo pridaných niekoľko metód, ktoré sa zhodovali s rozhraním EntityManager. Tieto metódy slúžia rovnakému účelu ako „pôvodné“ metódy, sú však v súlade so špecifikáciou a majú teda určité rozdiely.

3. Rozdiely medzi operáciami

Je dôležité od začiatku chápať, že všetky metódy (pretrvávať, uložiť, aktualizovať, zlúčiť, saveOrUpdate) nevedú okamžite k príslušnému SQL AKTUALIZÁCIA alebo VLOŽTE Vyhlásenia. K skutočnému uloženiu údajov do databázy dôjde pri spáchaní transakcie alebo prepláchnutí Session.

Uvedené metódy v zásade riadia stav inštančných entít ich prechodom medzi rôznymi stavmi počas životného cyklu.

Ako príklad entity použijeme jednoduchú entitu mapovanú anotáciami Osoba:

@Entity verejná trieda Osoba {@Id @GeneratedValue private Long id; súkromné ​​meno reťazca; // ... zakladatelia a zakladatelia}

3.1. Pretrvávať

The pretrvávať metóda je určená na pridanie novej inštancie entity do kontextu perzistencie, t. j. prechod inštancie z prechodného na vytrvalý štát.

Zvyčajne to nazývame, keď chceme pridať záznam do databázy (zachovať inštanciu entity):

Osoba osoba = nová osoba (); person.setName ("John"); session.persist (osoba);

Čo sa stane po pretrvávať metóda sa volá? The osoba objekt prešiel z prechodný do vytrvalý štát. Objekt je teraz v kontexte perzistencie, ale ešte nebol uložený do databázy. Generácia VLOŽTE príkazy sa objavia až po vykonaní transakcie, prepláchnutí alebo ukončení relácie.

Všimnite si, že pretrvávať metóda má neplatný návratový typ. Funguje na odovzdanom objekte „na mieste“ a mení jeho stav. The osoba premenná odkazuje na skutočný pretrvávajúci objekt.

Táto metóda je neskorším doplnkom rozhrania Session. Hlavným rozlišovacím znakom tejto metódy je, že vyhovuje špecifikácii JSR-220 (vytrvalosť EJB). Sémantika tejto metódy je striktne definovaná v špecifikácii, ktorá v podstate uvádza, že:

  • a prechodný inštancia sa stáva vytrvalý (a operácia sa tiahne k všetkým jej vzťahom s kaskáda = PERSIST alebo kaskáda = VŠETKY),
  • ak už inštancia existuje vytrvalý, potom táto výzva nemá žiadny vplyv na tento konkrétny prípad (stále však nadväzuje na jej vzťahy s kaskáda = PERSIST alebo kaskáda = VŠETKY),
  • ak je inštancia oddelený, mali by ste očakávať výnimku, a to buď pri vyvolaní tejto metódy, alebo pri spáchaní alebo prepláchnutí relácie.

Všimnite si, že tu nie je nič, čo by sa týkalo identifikátora inštancie. V špecifikácii sa neuvádza, že ID sa vygeneruje okamžite, bez ohľadu na stratégiu generovania ID. Špecifikácia pretrvávať metóda umožňuje implementácii vydávať príkazy na generovanie id pri potvrdení alebo prepláchnutí a po vyvolaní tejto metódy nie je zaručené, že id bude null, takže by ste sa na ňu nemali spoliehať.

Túto metódu môžete už zavolať vytrvalý napríklad a nič sa nedeje. Ale ak sa pokúsite vytrvať a oddelený Napríklad implementácia určite spôsobí výnimku. V nasledujúcom príklade sme pretrvávať subjekt, vysťahovať to z kontextu tak sa to stane oddelený, a potom skúste pretrvávať ešte raz. Druhá výzva session.persist () spôsobí výnimku, takže nasledujúci kód nebude fungovať:

Osoba osoba = nová Osoba (); person.setName ("John"); session.persist (osoba); session.evict (osoba); session.persist (osoba); // Výnimka Persistence!

3.2. Uložiť

The uložiť metóda je „pôvodná“ metóda dlhodobého spánku, ktorá nezodpovedá špecifikácii JPA.

Jeho účel je v zásade rovnaký ako pretrvávať, ale má odlišné podrobnosti implementácie. Dokumentácia k tejto metóde striktne uvádza, že trvá na inštancii, „najskôr priradí vygenerovaný identifikátor“. Metóda zaručene vráti Serializovateľné hodnota tohto identifikátora.

Osoba osoba = nová Osoba (); person.setName ("John"); Long id = (Long) session.save (person);

Účinok uloženia už pretrvávajúcej inštancie je rovnaký ako pri pretrvávať. Rozdiel nastane, keď sa pokúsite uložiť a oddelený inštancia:

Osoba osoba = nová Osoba (); person.setName ("John"); Long id1 = (Long) session.save (person); session.evict (osoba); Long id2 = (Long) session.save (person);

The id2 premenná sa bude líšiť od id1. Výzva na uloženie na a oddelený inštancia vytvorí nový vytrvalý inštancia a priradí jej nový identifikátor, ktorého výsledkom bude duplikátny záznam v databáze pri spáchaní alebo prepláchnutí.

3.3. Zlúčiť

Hlavným zámerom zlúčiť metóda je aktualizovať a vytrvalý inštancia entity s novými hodnotami poľa z a oddelený inštancia entity.

Predpokladajme napríklad, že máte rozhranie RESTful s metódou na získanie objektu serializovaného vo formáte JSON podľa jeho id volajúcemu a metódou, ktorá od volajúceho dostane aktualizovanú verziu tohto objektu. Entita, ktorá prešla takouto serializáciou / deserializáciou, sa objaví v a oddelený štát.

Po deserializácii tejto inštancie entity musíte získať a vytrvalý inštancia entity z kontextu pretrvávania a aktualizovať jej polia novými hodnotami z tohto oddelený inštancia. Takže zlúčiť metóda robí presne toto:

  • vyhľadá inštanciu entity podľa id prevzatého z odovzdaného objektu (buď sa získa existujúca inštancia entity z kontextu perzistencie, alebo sa z databázy načíta nová inštancia);
  • skopíruje polia z odovzdaného objektu do tejto inštancie;
  • vráti novo aktualizovanú inštanciu.

V nasledujúcom príklade sme vysťahovať (odpojiť) uloženú entitu od kontextu, zmeňte názov pole a potom zlúčiť the oddelený subjekt.

Osoba osoba = nová Osoba (); person.setName ("John"); session.save (osoba); session.evict (osoba); person.setName ("Mary"); Osoba mergedPerson = (Person) session.merge (person);

Všimnite si, že zlúčiť metóda vracia objekt - je to zlúčená osoba objekt, ktorý bol načítaný do kontextu perzistencie a aktualizovaný, nie osoba objekt, ktorý ste prešli ako argument. Jedná sa o dva rôzne objekty a osoba objekt je zvyčajne potrebné zahodiť (každopádne nepočítajte s tým, že bude pripojený k kontextu vytrvalosti).

Ako s pretrvávať metóda, zlúčiť metóda je špecifikovaná v JSR-220, aby mala určitú sémantiku, na ktorú sa môžete spoľahnúť:

  • ak účtovná jednotka je oddelený, skopíruje sa do existujúceho vytrvalý subjekt;
  • ak účtovná jednotka je prechodný, skopíruje sa do novo vytvoreného vytrvalý subjekt;
  • táto operácia kaskáduje všetky vzťahy s kaskáda = ZLÚČIŤ alebo kaskáda = VŠETKY mapovanie;
  • ak účtovná jednotka je vytrvalý, potom toto volanie metódy nemá na to vplyv (ale kaskádové usporiadanie stále prebieha).

3.4. Aktualizácia

Ako s pretrvávať a uložiť, aktualizovať metóda je „originálna“ metóda dlhodobého spánku, ktorá bola prítomná dávno pred zlúčiť bola pridaná metóda. Jeho sémantika sa líši v niekoľkých kľúčových bodoch:

  • pôsobí na odovzdaný objekt (jeho návratový typ je neplatný); the aktualizovať metóda premieňa odovzdaný objekt z oddelený do vytrvalý štát;
  • táto metóda vyvolá výnimku, ak ju splníte a prechodný subjekt.

V nasledujúcom príklade sme uložiť objekt vysťahovať (odpojiť) od kontextu, potom zmeňte jeho názov a zavolaj aktualizovať. Všimnite si, že nedávame výsledok aktualizovať operácia v samostatnej premennej, pretože aktualizovať sa koná na osoba samotný objekt. V zásade opätovne pripájame existujúcu inštanciu entity k kontextu vytrvalosti - niečo, čo nám špecifikácia JPA neumožňuje.

Osoba osoba = nová Osoba (); person.setName ("John"); session.save (osoba); session.evict (osoba); person.setName ("Mary"); session.update (osoba);

Skúšam volať aktualizovať na a prechodný inštancia bude mať za následok výnimku. Nasledujúce nebudú fungovať:

Osoba osoba = nová osoba (); person.setName ("John"); session.update (osoba); // Výnimka Persistence!

3.5. SaveOrUpdate

Táto metóda sa objavuje iba v rozhraní Hibernate API a nemá svojho štandardizovaného partnera. Podobný aktualizovať, môže sa tiež použiť na opätovné pripojenie inštancií.

Vlastne interné DefaultUpdateEventListener trieda, ktorá spracúva aktualizovať metóda je podtrieda DefaultSaveOrUpdateListener, iba prepísaním niektorých funkcií. Hlavný rozdiel saveOrUpdate metóda spočíva v tom, že pri použití na a prechodný inštancia; namiesto toho to robí prechodný inštancia vytrvalý. Nasledujúci kód zachová novovytvorenú inštanciu súboru Osoba:

Osoba osoba = nová Osoba (); person.setName ("John"); session.saveOrUpdate (osoba);

Túto metódu si môžete predstaviť ako univerzálny nástroj na výrobu predmetov vytrvalý bez ohľadu na to, v akom stave je prechodný alebo oddelený.

4. Čo použiť?

Ak nemáte žiadne špeciálne požiadavky, mali by ste sa držať pravidla pretrvávať a zlúčiť metódy, pretože sú štandardizované a zaručene zodpovedajú špecifikácii JPA.

Sú prenosné aj v prípade, že sa rozhodnete prejsť na iného poskytovateľa perzistencie, ale niekedy sa môžu javiť ako nie tak užitočné ako „pôvodné“ metódy dlhodobého spánku, uložiť, aktualizovať a saveOrUpdate.

5. Záver

Prediskutovali sme účel rôznych metód Hibernate Session vo vzťahu k správe perzistentných entít za behu. Dozvedeli sme sa, ako tieto metódy prechádzajú inštanciami entít počas ich životných cyklov a prečo majú niektoré z týchto metód duplikovanú funkčnosť.

Zdrojový kód článku je k dispozícii na GitHub.


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