Hibernate: save, persist, update, merge, saveOrUpdate

Bevezetés

ebben a cikkben a munkamenet interfész több módszere közötti különbségeket tárgyaljuk: Mentés, persist, update, merge, saveOrUpdate.

ez nem a hibernálás bevezetése, és már ismernie kell a konfiguráció alapjait, az objektum-relációs leképezést és az entitáspéldányokkal való munkát. A hibernálás bevezető cikkéhez keresse fel a Hibernate 4 tavaszi bemutatóját.

További információ:

objektumok törlése Hibernate

gyors útmutató egy entitás törléséhez Hibernate-ben.
Olvass tovább →

tárolt eljárások Hibernate

ez a cikk röviden bemutatja, hogyan hívhatja meg a Hibernate tárolási eljárásait.
Olvass tovább →

az azonosítók áttekintése Hibernate/JPA

Ismerje meg, hogyan lehet leképezni az entitásazonosítókat a Hibernate segítségével.
Olvass tovább →

munkamenet Perzisztencia kontextus Implementációként

a munkamenet interfész számos módszerrel rendelkezik, amelyek végül adatokat mentenek az adatbázisba: fennmarad, mentés, frissítés, egyesítés, saveOrUpdate. A módszerek közötti különbség megértéséhez először meg kell vitatnunk a munkamenet célját, mint perzisztencia kontextust, valamint az entitáspéldányok állapota közötti különbséget a munkamenethez viszonyítva.

meg kell értenünk a hibernált fejlesztés történetét is, amely néhány részben duplikált API-módszerhez vezetett.

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

magán az objektum-relációs leképezésen kívül a hibernálás egyik problémája az entitások futásidejű kezelésének problémája. A” perzisztencia kontextus ” fogalma a Hibernate megoldása erre a problémára. A perzisztencia kontextus tárolónak vagy első szintű gyorsítótárnak tekinthető az összes objektum számára, amelyet egy munkamenet során betöltött vagy elmentett egy adatbázisba.

a munkamenet egy logikai tranzakció, amelynek határait az alkalmazás üzleti logikája határozza meg. Ha perzisztencia-környezetben dolgozik az adatbázissal, és az összes entitáspéldánya ehhez a környezethez van csatolva, minden olyan adatbázisbejegyzéshez mindig legyen egy entitáspéldánya, amellyel a munkamenet során interakcióba lépett.

hibernált állapotban a perzisztencia kontextust az org képviseli.hibernálás.Session példány. A JPA számára ez a javax.kitartás.EntityManager. Amikor a Hibernate-et JPA szolgáltatóként használjuk, és EntityManager interfészen keresztül működünk, akkor ennek az interfésznek a megvalósítása alapvetően beburkolja az alapul szolgáló Session objektumot. A Hibernate Session azonban gazdagabb felületet biztosít, több lehetőséggel, így néha hasznos a Session közvetlen használata.

2.2. Entitáspéldányok állapota

az alkalmazás bármely entitáspéldánya a három fő állapot egyikében jelenik meg a munkamenet-perzisztencia környezethez viszonyítva:

  • tranziens-ez a példány nincs csatolva egy munkamenethez, és soha nem is volt csatolva; ennek a példánynak nincsenek megfelelő sorai az adatbázisban; általában csak egy új objektum, amelyet az adatbázisba történő mentéshez hozott létre;
  • persistent — ez a példány egy egyedi Munkamenetobjektumhoz van társítva; a munkamenet adatbázisba történő átöblítésekor ennek az entitásnak garantáltan megfelelő konzisztens rekordja lesz az adatbázisban;
  • leválasztva — ezt a példányt egyszer csatolták egy munkamenethez (állandó állapotban), de most nem az; egy példány akkor lép be ebbe az állapotba, ha kilakoltatja a kontextusból, törli vagy bezárja a munkamenetet, vagy a példányt sorosítási/deszerializációs folyamaton végzi.

itt található egy egyszerűsített állapotdiagram, amely megjegyzéseket tartalmaz az Állapotátmeneteket lehetővé tevő munkamenet-módszerekről.

2016-07-11_13-38-11

ha az entitáspéldány állandó állapotban van, a példány leképezett mezőin végrehajtott összes módosítást a rendszer alkalmazza a megfelelő adatbázisrekordokra és mezőkre a munkamenet öblítésekor. Az állandó példány “online” – nak tekinthető, míg a leválasztott példány “offline” lett, és nem figyeli a változásokat.

ez azt jelenti, hogy egy állandó objektum mezőinek megváltoztatásakor nem kell meghívnia a mentést, a frissítést vagy a fenti módszerek bármelyikét, hogy megkapja ezeket a módosításokat az adatbázisban: mindössze annyit kell tennie, hogy végrehajtja a tranzakciót, vagy öblítse le vagy zárja be a munkamenetet, ha végzett vele.

2.3. A JPA specifikációnak való megfelelés

a Hibernate volt a legsikeresebb Java ORM implementáció. 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 nagyobb, néhány finomabb.

ahhoz, hogy a JPA szabvány implementációjaként működjön, a Hibernate API-kat felül kellett vizsgálni. Számos módszer került hozzáadásra a Session interface-hez, hogy megfeleljen az EntityManager felületnek. Ezek a módszerek ugyanazt a célt szolgálják, mint az” eredeti ” módszerek, de megfelelnek a specifikációnak, így vannak bizonyos különbségek.

a műveletek közötti különbségek

a kezdetektől fontos megérteni, hogy az összes módszer (persist, save, update, merge, saveOrUpdate) nem eredményezi azonnal a megfelelő SQL UPDATE vagy INSERT utasításokat. Az adatok tényleges mentése az adatbázisba a tranzakció végrehajtásakor vagy a munkamenet öblítésekor történik.

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

mint például entitás, egy egyszerű annotációval leképezett entitás személyt fogunk használni:

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

3.1. Persist

a persist metódus egy új entitáspéldány hozzáadására szolgál a perzisztencia környezethez, azaz egy példány tranziens állapotból perzisztens állapotba való átmenetére.

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

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

mi történik a persist módszer hívása után? A személy objektum átmeneti állapotból tartós állapotba került. Az objektum most a perzisztencia kontextusban van, de még nincs mentve az adatbázisba. A beszúrási utasítások generálása csak a tranzakció elkövetésekor, a munkamenet öblítésekor vagy bezárásakor történik.

figyeljük meg, hogy a persist módszer érvénytelen visszatérési típus. Az átadott objektumon “a helyén” működik, megváltoztatva annak állapotát. A person változó a tényleges perzisztens objektumra hivatkozik.

ez a módszer a munkamenet-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:

  • egy átmeneti példány perzisztenssé válik (és a művelet kaszkádol a cascade=PERSIST vagy cascade=ALL összes kapcsolatához),
  • ha egy példány már perzisztens, akkor ennek a hívásnak nincs hatása erre a konkrét példányra (de még mindig kaszkádol a cascade=PERSIST vagy cascade=ALL kapcsolataihoz),
  • ha egy példány leválik, akkor kivételre számíthat, akár a metódus meghívásakor, akár a munkamenet lekötésekor vagy öblítésekor.

vegye figyelembe, hogy itt nincs semmi, ami egy példány azonosítójára vonatkozik. A specifikáció nem állítja, hogy az azonosítót azonnal generálják, függetlenül az azonosítógenerálási stratégiától. A persist metódus specifikációja lehetővé teszi az implementáció számára, hogy utasításokat adjon ki az azonosító létrehozására a commit vagy a flush során, és az azonosító nem garantáltan nem null a metódus meghívása után, ezért nem szabad támaszkodnia rá.

meghívhatja ezt a módszert egy már állandó példányon, és semmi sem történik. De ha megpróbál fennmaradni egy különálló példányt, a megvalósítás köteles kivételt dobni. A következő példában kitartjuk az entitást, kilakoltatjuk a kontextusból, így leválik, majd megpróbálunk újra fennmaradni. A második ülés összehívása.persist () kivételt okoz, így a következő kód nem fog működni:

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

3.2. Save

a mentési módszer egy “eredeti” hibernált módszer, amely nem felel meg a JPA specifikációnak.

célja alapvetően ugyanaz, mint a persist, de különböző végrehajtási részletekkel rendelkezik. Ennek a módszernek a dokumentációja szigorúan kimondja, hogy továbbra is fennáll a példány, “először hozzárendel egy generált azonosítót”. A módszer garantáltan visszaadja az azonosító Sorosítható értékét.

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

a már fennmaradt példány mentésének hatása ugyanaz, mint a persistnél. A különbség akkor jön létre, amikor megpróbál menteni egy különálló példányt:

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

az id2 változó eltér az id1-től. A mentés egy leválasztott példányon hívása új állandó példányt hoz létre, és új azonosítót rendel hozzá, amely az elkövetés vagy az öblítés során duplikált rekordot eredményez az adatbázisban.

3.3. Merge

az egyesítési módszer fő célja egy állandó entitáspéldány frissítése egy leválasztott entitáspéldány új mezőértékeivel.

tegyük fel például, hogy van egy RESTful interfésze egy metódussal egy JSON-sorosított objektum lekérésére az azonosítója alapján a hívónak, és egy metódussal, amely az objektum frissített verzióját fogadja a hívótól. Az ilyen szerializáción/dezerializáción átesett entitás különálló állapotban jelenik meg.

az entitáspéldány deszerializálása után be kell szereznie egy perzisztens entitáspéldányt egy perzisztencia környezetből, és frissítenie kell a mezőit a leválasztott példány új értékeivel. Tehát az egyesítési módszer pontosan ezt teszi:

  • az átadott objektumból vett entitáspéldányt id alapján találja meg (vagy a perzisztencia környezetből egy meglévő entitáspéldányt lekér, vagy egy új példányt tölt be az adatbázisból);
  • az átadott objektum mezőit másolja erre a példányra;
  • az újonnan frissített példányt adja vissza.

a következő példában kilakoltatjuk (leválasztjuk) a mentett entitást a környezetből, megváltoztatjuk a név mezőt, majd egyesítjük a leválasztott entitást.

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

vegye figyelembe, hogy az egyesítési módszer egy objektumot ad vissza — ez a perzisztencia környezetbe betöltött és frissített mergedPerson objektum, nem pedig az argumentumként átadott személy objektum. Ez két különböző objektum, és a személy objektumot általában el kell dobni (egyébként ne számítson arra, hogy a perzisztencia kontextushoz kapcsolódik).

a persist módszerhez hasonlóan az egyesítési módszert a JSR-220 határozza meg, hogy bizonyos szemantikával rendelkezzen, amelyre támaszkodhat:

  • ha az entitás leválasztva van, akkor egy meglévő állandó entitásra másolja;
  • ha az entitás tranziens, akkor egy újonnan létrehozott állandó entitásra másolja;
  • ez a művelet a cascade=MERGE vagy cascade=ALL leképezés összes kapcsolatára kaszkádol;
  • ha az entitás perzisztens, akkor ez a metódushívás nincs hatással rá (de a lépcsőzetes továbbra is megtörténik).

3.4. Update

a persist and save-hez hasonlóan a frissítési módszer egy “eredeti” hibernált módszer, amely jóval az egyesítési módszer hozzáadása előtt volt jelen. Szemantikája több kulcsfontosságú pontban különbözik:

  • az átadott objektumra hat (visszatérési típusa érvénytelen); a frissítési módszer az átadott objektumot leválasztott állapotból állandó állapotba állítja;
  • ez a módszer kivételt dob, ha tranziens entitásnak adja át.

a következő példában mentjük az objektumot, majd kilakoltatjuk (leválasztjuk) a kontextusból, majd megváltoztatjuk a nevét és meghívjuk a frissítést. Vegye figyelembe, hogy a frissítési művelet eredményét nem külön változóba tesszük, mert a frissítés magán a személy objektumon történik. Alapvetően a meglévő entitáspéldányt visszahelyezzük a perzisztencia környezetbe — amit a JPA specifikáció nem enged meg nekünk.

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

a frissítés meghívása egy átmeneti példányon kivételt eredményez. A következők nem működnek:

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

3.5. SaveOrUpdate

ez a módszer csak a Hibernate API-ban jelenik meg, és nincs szabványosított megfelelője. Hasonló a frissítés, azt is fel lehet használni a visszahelyezése példányok.

valójában a frissítési módszert feldolgozó belső DefaultUpdateEventListener osztály a DefaultSaveOrUpdateListener alosztálya, csak felülír néhány funkciót. A saveOrUpdate metódus fő különbsége az, hogy nem dob kivételt, ha átmeneti példányra alkalmazzák; ehelyett ezt az átmeneti példányt állandóvá teszi. A következő kód megmarad egy újonnan létrehozott Személypéldány:

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

erre a módszerre úgy gondolhat, mint egy univerzális eszközre, amely egy objektumot állandóvá tesz, függetlenül annak állapotától, függetlenül attól, hogy átmeneti vagy leválasztott-e.

mit kell használni?

ha nincsenek speciális követelményei, ökölszabályként ragaszkodjon a persist és merge módszerekhez, mert szabványosítottak és garantáltan megfelelnek a JPA specifikációnak.

hordozhatóak abban az esetben is, ha úgy dönt, hogy másik perzisztencia szolgáltatóra vált, de néha úgy tűnik, hogy nem olyan hasznosak, mint az “eredeti” hibernált módszerek, mentés, frissítés és saveOrUpdate.

következtetés

megvitattuk a különböző hibernált munkamenet-módszerek célját a tartós entitások futásidejű kezelésével kapcsolatban. Megtanultuk, hogy ezek a módszerek hogyan tranzisztálják az entitáspéldányokat életciklusukon keresztül, és miért vannak ezek a módszerek duplikált funkcionalitással.



+