Objektové štáty v relácii Hibernate
1. Úvod
Hibernate je vhodný rámec na správu trvalých údajov, ale pochopenie toho, ako to funguje interne, môže byť niekedy zložité.
V tomto tutoriále sa dozvieme o stavoch objektov a o tom, ako sa medzi nimi pohybovať. Pozrime sa tiež na problémy, s ktorými sa môžeme stretnúť s odpojenými entitami, a na to, ako ich vyriešiť.
2. Relácia dlhodobého spánku
The Session rozhranie je hlavným nástrojom používaným na komunikáciu s režimom dlhodobého spánku. Poskytuje API, ktoré nám umožňuje vytvárať, čítať, aktualizovať a mazať trvalé objekty. The zasadanie má jednoduchý životný cyklus. Otvoríme ho, vykonáme nejaké operácie a potom ho zavrieme.
Keď operujeme objekty počas zasadanie, pripútajú sa k tomu zasadanie. Zmeny, ktoré vykonáme, sa zistia a uložia po uzavretí. Po zatvorení režim dlhodobého spánku preruší spojenia medzi objektmi a reláciou.
3. Objektové štáty
V kontexte režimu dlhodobého spánku Session, objekty môžu byť v jednom z troch možných stavov: prechodný, pretrvávajúci alebo odpojený.
3.1. Prechodné
Objekt, ktorý sme k žiadnemu nepripojili zasadanie je v prechodnom stave. Pretože nikdy nepretrvával, nemá v databáze žiadne zastúpenie. Pretože nie zasadanie vie o tom, neuloží sa automaticky.
Vytvorme objekt používateľa s konštruktorom a potvrdíme, že ho nespravuje relácia:
Relácia session = openSession (); UserEntity userEntity = new UserEntity ("John"); assertThat (session.contains (userEntity)). isFalse ();
3.2. Vytrvalé
Objekt, ktorý sme spojili s a zasadanie je v trvalom stave. Buď sme ho uložili, alebo prečítali z kontextu vytrvalosti, takže predstavuje nejaký riadok v databáze.
Vytvorme objekt a potom použite pretrvávať spôsob, ako to urobiť perzistentným:
Relácia session = openSession (); UserEntity userEntity = new UserEntity ("John"); session.persist (userEntity); assertThat (session.contains (userEntity)). isTrue ();
Prípadne môžeme použiť uložiť metóda. Rozdiel je v tom, že pretrvávať metóda iba uloží objekt a uložiť metóda bude navyše generovať svoj identifikátor, ak je to potrebné.
3.3. Oddelený
Keď zavrieme zasadanie, všetky objekty v jeho vnútri sa oddelia. Aj keď stále predstavujú riadky v databáze, už ich nikto nespravuje zasadanie:
session.persist (userEntity); session.close (); assertThat (session.isOpen ()). isFalse (); assertThatThrownBy (() -> session.contains (userEntity));
Ďalej sa naučíme, ako ukladať prechodné a oddelené entity.
4. Uloženie a opätovné pripojenie entity
4.1. Uloženie prechodnej entity
Vytvorme novú entitu a uložme ju do databázy. Keď prvýkrát postavíme objekt, bude v prechodnom stave.
To pretrvávať náš nový subjekt, použijeme pretrvávať metóda:
UserEntity userEntity = new UserEntity ("John"); session.persist (userEntity);
Teraz vytvoríme ďalší objekt s rovnakým identifikátorom ako prvý. Tento druhý objekt je prechodný, pretože ho zatiaľ nikto nespravuje zasadanie, ale nemôžeme to dosiahnuť trvalým používaním pretrvávať metóda. Je už zastúpený v databáze, takže v kontexte vrstvy perzistencie nie je skutočne nový.
Namiesto toho použijeme zlúčiť metóda na aktualizáciu databázy a zabezpečenie perzistentnosti objektu:
UserEntity onceAgainJohn = nový UserEntity ("John"); session.merge (onceAgainJohn);
4.2. Uloženie odpojenej entity
Ak zavrieme predošlé zasadanie, naše objekty budú v odpojenom stave. Podobne ako v predchádzajúcom príklade sú zastúpené v databáze, ale v súčasnosti ich nikto nespravuje zasadanie. Môžeme ich znova urobiť perzistentnými pomocou zlúčiť metóda:
UserEntity userEntity = new UserEntity ("John"); session.persist (userEntity); session.close (); session.merge (userEntity);
5. Vnorené subjekty
Veci sa komplikujú, keď vezmeme do úvahy vnorené entity. Povedzme, že naša používateľská entita bude tiež ukladať informácie o svojom manažérovi:
verejná trieda UserEntity {@Id súkromné meno reťazca; @ManyToOne súkromný manažér UserEntity; }
Keď ukladáme túto entitu, musíme myslieť nielen na stav samotnej entity, ale aj na stav vnorenej entity. Vytvorme entitu trvalého používateľa a potom nastavíme jej správcu:
UserEntity userEntity = new UserEntity ("John"); session.persist (userEntity); UserEntity manager = nový UserEntity ("Adam"); userEntity.setManager (manažér);
Ak sa ju pokúsime aktualizovať hneď, dostaneme výnimku:
assertThatThrownBy (() -> {session.saveOrUpdate (userEntity); transaction.commit ();});
java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: objekt odkazuje na neuloženú prechodnú inštanciu - uložte prechodnú inštanciu pred vyprázdnením: com.baeldung.states.UserEntity.manager -> com.baeldung.states.UserEntity
To sa deje, pretože Hibernate nevie, čo má robiť s prechodnou vnorenou entitou.
5.1. Pretrvávajúce vnorené subjekty
Jedným zo spôsobov riešenia tohto problému je výslovne pretrvávať vnorené entity:
UserEntity manager = nový UserEntity ("Adam"); session.persist (manažér); userEntity.setManager (manažér);
Potom po vykonaní transakcie budeme môcť získať správne uloženú entitu:
transaction.commit (); session.close (); Relácia otherSession = openSession (); UserEntity savedUser = otherSession.get (UserEntity.class, "John"); assertThat (savedUser.getManager (). getName ()). isEqualTo ("Adam");
5.2. Kaskádové operácie
Prechodné vnorené entity je možné automaticky zachovať, ak nakonfigurujeme vzťah kaskáda vlastnosť správne v triede entít:
@ManyToOne (cascade = CascadeType.PERSIST) súkromný manažér UserEntity;
Teraz, keď objekt pretrvávame, bude táto operácia kaskádovo pripojená ku všetkým vnoreným entitám:
UserEntityWithCascade userEntity = nový UserEntityWithCascade ("John"); session.persist (userEntity); UserEntityWithCascade manager = nový UserEntityWithCascade ("Adam"); userEntity.setManager (manažér); // pridať prechodového manažéra k trvalej relácii používateľa.saveOrUpdate (userEntity); transaction.commit (); session.close (); Relácia otherSession = openSession (); UserEntityWithCascade savedUser = otherSession.get (UserEntityWithCascade.class, "John"); assertThat (savedUser.getManager (). getName ()). isEqualTo ("Adam");
6. Zhrnutie
V tomto tutoriáli sme sa bližšie pozreli na to, ako je režim dlhodobého spánku Session pracuje s ohľadom na stav objektu. Potom sme skontrolovali niektoré problémy, ktoré môže spôsobiť, a spôsoby ich riešenia.
Ako vždy, zdrojový kód je k dispozícii na GitHub.