Hibernálás: mentés, kitartás, frissítés, egyesítés, saveOrUpdate

1. Bemutatkozás

Ebben a cikkben megvitatjuk a különböző módszerek közötti különbségeket Ülés felület: mentés, kitartanak, frissítés, összeolvad, saveOrUpdate.

Ez nem a hibernálás bevezetése, és már ismernie kell a konfigurálás, az objektum-reláció leképezés és az entitáspéldányokkal való munka alapjait. A Hibernate bevezető cikkéhez keresse fel a Hibernate 4 with Spring című oktatóanyagunkat.

2. A munkamenet mint perzisztencia-kontextus megvalósítása

A Ülés Az interfésznek számos módszere van, amelyek végül adatokat mentenek az adatbázisba: kitartanak, mentés, frissítés, összeolvad, saveOrUpdate. E módszerek közötti különbség megértéséhez először meg kell vitatnunk a módszer célját Ülés mint állandósági kontextus és az entitáspéldányok állapota közötti különbség a Ülés.

Meg kell értenünk a hibernált fejlesztés történetét is, amely részben megismétlődő API-módszerekhez vezetett.

2.1. Entitáspéldányok kezelése

Az objektum-relációs leképezésen kívül az egyik probléma, amelyet a Hibernate megoldani kívánt, az entitások futás közbeni kezelésének problémája. A „kitartási kontextus” fogalma Hibernate megoldása erre a problémára. A perzisztencia-kontextust úgy lehet elképzelni, mint egy tárolót vagy egy első szintű gyorsítótárat minden olyan objektum számára, amelyet egy munkamenet során betöltött vagy adatbázisba mentett.

A munkamenet logikai tranzakció, amelyet a határokat az alkalmazás üzleti logikája határoz meg. Ha az adatbázissal egy perzisztencia-kontextuson keresztül dolgozik, és az összes entitáspéldánya ehhez a kontextushoz van csatolva, akkor mindig egyetlen entitás-példánnyal kell rendelkeznie minden adatbázis-rekord számára, amellyel a munkamenet során kölcsönhatásba lépett.

A hibernált állapotban a kitartási kontextust a org.hibernate.Session példa. A JPA számára ez a javax.persistence.EntityManager. Amikor a Hibernate programot JPA szolgáltatóként használjuk, és ezen keresztül működünk EntityManager interfész, ennek a felületnek a megvalósítása alapvetően beburkolja az alapul szolgálót Ülés tárgy. Azonban Hibernate Ülés gazdagabb felületet kínál, több lehetőséggel, így néha hasznos vele dolgozni Közvetlenül a munkamenet.

2.2. Entitáspéldányok állapota

Bármely entitáspéldány az alkalmazásban a három fő állapot egyikében jelenik meg Ülés kitartás összefüggései:

  • átmeneti - ez a példány nem, és soha nem is volt a Ülés; ennek a példánynak nincs megfelelő sora az adatbázisban; ez általában csak egy új objektum, amelyet létrehozott az adatbázisba mentésre;
  • kitartó - ez a példány egyedi Ülés tárgy; öblítéskor a Ülés az adatbázis számára ennek az entitásnak garantáltan megfelelő konzisztens rekordja lesz az adatbázisban;
  • különálló - ezt a példányt egykor a Ülés (a kitartó állam), de most nem az; egy példány belép ebbe az állapotba, ha kiteszi a kontextusból, törli vagy bezárja a munkamenetet, vagy a példányt sorosítási / deserializációs folyamaton keresztül helyezi el.

Itt van egy egyszerűsített állapotdiagram megjegyzésekkel Ülés az állapotátmeneteket megvalósító módszerek.

Amikor az entitáspéldány a kitartó állapotban, a példány leképezett mezőiben végrehajtott összes változtatás a megfelelő adatbázis-rekordokra és mezőkre lesz alkalmazva a Ülés. A kitartó példány „online” -nek tekinthető, míg az különálló a példány „offline” állapotba került, és nem figyelik a változásokat.

Ez azt jelenti, hogy amikor megváltoztatja a kitartó objektum, akkor nem kell telefonálnia mentés, frissítés vagy bármelyik módszer a változtatások adatbázisba juttatásához: csak a tranzakció végrehajtására vagy a munkamenet átmosására vagy bezárására van szükség, ha ezzel végzett.

2.3. A JPA előírásainak való megfelelés

A hibernálás volt a legsikeresebb Java ORM megvalósítás. Nem csoda, hogy a Java persistence API (JPA) specifikációját erősen befolyásolta a Hibernate API. Sajnos sok különbség is volt: néhány fő, másik finomabb.

A JPA szabvány megvalósításaként a Hibernate API-kat felül kellett vizsgálni. Számos módszert adtak a Session felülethez, hogy megfeleljenek az EntityManager felületének. Ezek a módszerek ugyanazt a célt szolgálják, mint az „eredeti” módszerek, de megfelelnek a specifikációnak, és ezért vannak némi eltérésük.

3. Különbségek a műveletek között

Fontos kezdettől fogva megérteni, hogy az összes módszer (kitartanak, mentés, frissítés, összeolvad, saveOrUpdate) nem eredményezi azonnal a megfelelő SQL-t FRISSÍTÉS vagy INSERT nyilatkozatok. Az adatok tényleges mentése az adatbázisba a tranzakció végrehajtása vagy a Ülés.

Az említett módszerek alapvetően úgy kezelik az entitáspéldányok állapotát, hogy az életciklusuk során átállítják őket a különböző állapotok között.

Példa entitásként egy egyszerű feljegyzéssel leképezett entitást fogunk használni Személy:

@Entity public class Person {@Id @GeneratedValue private Long id; privát karakterlánc neve; // ... getterek és beállítók}

3.1. Kitartani

A kitartanak A módszer célja egy új entitáspéldány hozzáadása a perzisztencia-kontextushoz, azaz egy példány átmenete átmenetiből a kitartó állapot.

Általában akkor hívjuk, amikor rekordot akarunk hozzáadni az adatbázishoz (megmarad egy entitáspéldány):

Személy személy = új Személy (); person.setName ("János"); munkamenet.ellenőr (személy);

Mi történik a kitartanak módszert hívják? A személy objektum átment a átmeneti nak nek kitartó állapot. Az objektum jelenleg a perzisztencia kontextusban van, de még nincs elmentve az adatbázisba. A nemzedék INSERT kimutatások csak a tranzakció végrehajtása, a munkamenet öblítése vagy lezárása után történnek.

Figyeljük meg, hogy a kitartani módszer van üres visszatérési típus. Az átadott objektumot „a helyén” működteti, megváltoztatva az állapotát. A személy a változó a tényleges fennmaradt objektumra hivatkozik.

Ez a módszer a Session felület későbbi kiegészítése. A módszer fő megkülönböztető jellemzője, hogy megfelel a JSR-220 specifikációnak (EJB perzisztencia). Ennek a módszernek a szemantikáját szigorúan meghatározza a specifikáció, amely alapvetően kimondja, hogy:

  • a átmeneti példány válik kitartó (és a művelet lépcsőzetesen kapcsolódik a kaszkád = PERSIST vagy kaszkád = MINDEN),
  • ha egy példány már az kitartó, akkor ennek a felhívásnak nincs hatása az adott példányra (de még mindig lépcsőzetes a kaszkád = PERSIST vagy kaszkád = MINDEN),
  • ha egy példány az különálló, kivételt kell várnia, vagy ennek a módszernek a meghívásakor, vagy a munkamenet végrehajtásakor vagy öblítésénél.

Figyelje meg, hogy itt semmi nem érinti a példány azonosítóját. A specifikáció nem állítja, hogy az id azonnal létrejön, függetlenül az id generációs stratégiától. A. Specifikációja kitartanak A metódus lehetővé teszi a megvalósítás számára, hogy utasításokat bocsásson ki az id generálásához a végrehajtáson vagy a flushon, és a metódus meghívása után nem garantált, hogy az id nem null lesz, ezért nem szabad rá hagyatkozni.

Hívhatja ezt a módszert már kitartó és semmi sem történik. De ha megpróbál kitartani a különálló Például a megvalósítás kivételt képez. A következő példában mi kitartanak az entitás, megszerez a kontextusból, így válik különálló, majd próbálja meg kitartanak újra. A második hívás session.persist () kivételt okoz, ezért a következő kód nem fog működni:

Személy személy = új Személy (); person.setName ("János"); munkamenet.ellenőr (személy); session.evict (személy); munkamenet.ellenőr (személy); // PersistenceException!

3.2. Mentés

A mentés A módszer egy „eredeti” hibernált módszer, amely nem felel meg a JPA specifikációjának.

Célja alapvetően megegyezik a kitartanak, de különböző megvalósítási részletei vannak. A módszer dokumentációja szigorúan kimondja, hogy a példány továbbra is fennáll, „először hozzon létre egy generált azonosítót”. A módszer garantáltan visszaadja a Sorosítható ennek az azonosítónak az értéke.

Személy személy = új Személy (); person.setName ("János"); Long id = (Long) session.save (személy);

A már fennálló példány mentésének hatása ugyanaz, mint a másikkal kitartani. A különbség akkor jön, amikor megpróbálja menteni a különálló példa:

Személy személy = új Személy (); person.setName ("János"); Long id1 = (Long) session.save (személy); session.evict (személy); Long id2 = (Long) session.save (személy);

A id2 változó különbözik a id1. A mentés hívása a különálló példány létrehoz egy új kitartó példányt, és hozzárendel egy új azonosítót, amely elkövetés vagy öblítéskor duplikált rekordot eredményez az adatbázisban.

3.3. Összeolvad

A fő szándék a összeolvad módszer a frissítés a kitartó entitáspéldány új mezőértékekkel a különálló entitáspéldány.

Tegyük fel például, hogy van egy RESTful interfész, amelynek módja van egy JSON-sorosított objektum lekérésére az azonosítója alapján a hívónak, és egy módszerrel, amely az objektum frissített verzióját kapja a hívótól. Az ilyen szerializáción / deszerializáción átesett entitás megjelenik a különálló állapot.

Az entitáspéldány deszerializálása után meg kell szereznie a kitartó entitáspéldány egy perzisztencia-kontextusból, és frissítse a mezőket ebből származó új értékekkel különálló példa. Így a összeolvad módszer pontosan ezt teszi:

  • megkeresi az entitáspéldányt az átadott objektumból vett azonosító alapján (vagy a meglévő entitáspéldány lekérésre kerül a perzisztencia-kontextusból, vagy új példányt tölt be az adatbázisból);
  • mezőket másol át az átadott objektumból erre a példányra;
  • az újonnan frissített példányt adja vissza.

A következő példában mi megszerez (leválaszthatja) a mentett entitást a kontextusról, módosíthatja a név mezőt, majd összeolvad a különálló entitás.

Személy személy = új Személy (); person.setName ("János"); session.save (személy); session.evict (személy); person.setName ("Mária"); Person mergedPerson = (Személy) session.merge (személy);

Vegye figyelembe, hogy a összeolvad metódus egy objektumot ad vissza - ez az mergedPerson a perzisztencia-kontextusba töltött és frissített objektum, nem a személy objektum, amelyet argumentumként adott át. Ez két különböző tárgy, és a személy az objektumot általában el kell dobni (különben sem számíthat arra, hogy a perzisztencia kontextushoz kapcsolódik).

Mint kitartani módszer, az összeolvad módszert a JSR-220 határozza meg, hogy rendelkezzen bizonyos szemantikával, amelyre támaszkodhat:

  • ha az entitás az különálló, egy létezőre másolja kitartó entitás;
  • ha az entitás az átmeneti, egy újonnan létrehozottra másolja kitartó entitás;
  • ez a művelet kaszkád minden kapcsolattal kaszkád = MERGE vagy kaszkád = MINDEN feltérképezés;
  • ha az entitás az kitartó, akkor ez a metódushívás nincs hatással rá (de a lépcsőzés mégis megtörténik).

3.4. Frissítés

Mint kitartanak és mentés, a frissítés módszer egy „eredeti” hibernált módszer, amely jóval a összeolvad módszert adtak hozzá. Szemantikája több kulcskérdésben különbözik:

  • átadott objektumra hat (visszatérési típusa üres); a frissítés metódus átadja az átadott objektumot különálló nak nek kitartó állapot;
  • ez a módszer kivételt vet, ha átadja a átmeneti entitás.

A következő példában mi mentés akkor az objektumot megszerez (leválasztani) a kontextusról, majd megváltoztatni név és hívjon frissítés. Figyeljük meg, hogy nem adjuk meg a frissítés művelet külön változóban, mert a frissítés zajlik a személy maga a tárgy. Alapvetően újból hozzákapcsoljuk a meglévő entitáspéldányt a perzisztencia-kontextushoz - ezt a JPA specifikáció nem teszi lehetővé.

Személy személy = új Személy (); person.setName ("János"); session.save (személy); session.evict (személy); person.setName ("Mária"); session.update (személy);

Hívni próbál frissítés rajta átmeneti példány kivételt eredményez. A következők nem fognak működni:

Személy személy = új Személy (); person.setName ("János"); session.update (személy); // PersistenceException!

3.5. SaveOrUpdate

Ez a módszer csak a Hibernate API-ban jelenik meg, és nincs szabványosított megfelelője. Hasonló frissítés, példányok újracsatolásához is használható.

Valójában a belső DefaultUpdateEventListener osztály, amely a frissítés módszer a DefaultSaveOrUpdateListener, csak felülír bizonyos funkciókat. A fő különbség saveOrUpdate módszer az, hogy nem vet ki kivételt, ha a átmeneti példa; ehelyett ezt teszi átmeneti példa kitartó. A következő kód megőrzi az újonnan létrehozott Személy:

Személy személy = új Személy (); person.setName ("János"); session.saveOrUpdate (személy);

Gondolhat erre a módszerre, mint egy tárgy készítésének univerzális eszközére kitartó állapotától függetlenül átmeneti vagy különálló.

4. Mit kell használni?

Ha nincs különösebb követelménye, akkor ökölszabályként ragaszkodjon a kitartani és összeolvad módszereket, mert szabványosítottak és garantáltan megfelelnek a JPA specifikációinak.

Hordozhatók abban az esetben is, ha úgy dönt, hogy másik állandó szolgáltatóra vált, de előfordulhat, hogy nem annyira hasznosak, mint az „eredeti” hibernált módszerek, mentés, frissítés és saveOrUpdate.

5. Következtetés

Megbeszéltük a különböző hibernált munkamenet-módszerek célját a tartós entitások futásidejű kezelésével kapcsolatban. Megtudtuk, hogy ezek a módszerek hogyan transzisztálják az entitáspéldányokat az életciklusuk során, és miért vannak ezeknek a módszereknek a duplikált funkcionalitása.

A cikk forráskódja elérhető a GitHubon.