Hibernált entitás életciklusa

1. Áttekintés

Minden hibernált entitásnak természetesen van egy életciklusa a keretrendszerben - akár átmeneti, felügyelt, leválasztott vagy törölt állapotban.

Ezeknek az állapotoknak a megértése koncepcionális és technikai szinten egyaránt elengedhetetlen a hibernálás megfelelő használatához.

Ha többet szeretne megtudni az entitásokkal foglalkozó különböző hibernált módszerekről, tekintse meg az egyik korábbi oktatóanyagunkat.

2. Segítő módszerek

A bemutató során következetesen több segítő módszert fogunk használni:

  • HibernateLifecycleUtil.getManagedEntities (munkamenet) - arra fogjuk használni, hogy az összes kezelt entitást megszerezzük a A munkamenet belső áruház
  • DirtyDataInspector.getDirtyEntities () - ezt a módszert arra használjuk, hogy összeállítsuk az összes „piszkosnak” jelölt entitást
  • HibernateLifecycleUtil.queryCount (lekérdezés) - kényelmes módszer számol(*) lekérdezés a beágyazott adatbázis ellen

A fenti segítő módszerek statikusan importálva vannak a jobb olvashatóság érdekében. A cikk végén linkelt GitHub projektben megtalálhatja megvalósításukat.

3. Minden a perzisztencia kontextusáról szól

Mielőtt belekezdenénk az entitás életciklusának témájába, először meg kell értenünk a kitartási kontextus.

Egyszerűen fogalmazva: kitartás összefüggései az ügyfél kódja és az adattár között helyezkedik el. Ez egy átmeneti terület, ahol a tartós adatokat entitásokká alakítják, készen állnak olvasásra és az ügyfélkód módosítására.

Elméletileg a kitartás összefüggései a Unit of Work minta megvalósítása. Nyomon követi az összes betöltött adatot, nyomon követi az adatok változását, és felelős azért, hogy az üzleti tranzakció végén az esetleges változásokat visszaszinkronizálja az adatbázisba.

JPA EntityManager és a Hibernate-é Ülés megvalósítása kitartás összefüggései koncepció. Ebben a cikkben a hibernált módot fogjuk használni Ülés képviselni kitartás összefüggései.

A hibernált entitás életciklusának állapota elmagyarázza, hogy az entitás hogyan kapcsolódik a kitartás összefüggései, amint ezt majd meglátjuk.

4. Felügyelt entitás

A kezelt entitás az adatbázis táblasorának ábrázolása (bár ennek a sornak még nem kell léteznie az adatbázisban).

Ezt a jelenleg futó kezeli Ülés, és minden rajta végrehajtott változtatást nyomon követnek és automatikusan továbbítják az adatbázisba.

A Ülés vagy betölti az entitást az adatbázisból, vagy újracsatol egy leválasztott entitást. A leválasztott entitásokat az 5. szakaszban tárgyaljuk.

Nézzünk meg néhány kódot, hogy tisztázzuk.

Alkalmazásmintánk egy entitást, a Focista osztály. Indításkor inicializáljuk az adattárat néhány mintaadattal:

+ ------------------- + ------- + | Név | ID | + ------------------- + ------- + | Cristiano Ronaldo | 1. | | Lionel Messi | 2 | | Gianluigi Buffon 3 | + ------------------- + ------- +

Tegyük fel, hogy kezdetben meg akarjuk változtatni Buffon nevét - be akarjuk írni a teljes nevét Gianluigi Buffon Gigi Buffon helyett.

Először is el kell kezdenünk a munkaegységünket a Ülés:

Munkamenet = sessionFactory.openSession ();

Szerver környezetben beadhatunk egy Ülés kontextusfigyelő proxy segítségével a kódunkhoz. Az elv ugyanaz marad: szükségünk van a Ülés beilleszteni munkánk egységének üzleti tranzakcióját.

Ezután megtanítjuk a sajátunkat Ülés az adatok feltöltése a tartós tárolóból:

assertThat (getManagedEntities (munkamenet)). isEmpty (); Játékosok listája = s.createQuery ("from FootballPlayer"). GetResultList (); assertThat (getManagedEntities (munkamenet)). size (). isEqualTo (3); 

Amikor először megszerezzük a Ülés, az állandó kontextustárolója üres, amint azt az elsőnk is mutatja állítják nyilatkozat.

Ezután végrehajtunk egy lekérdezést, amely lekérdezi az adatokat az adatbázisból, létrehozza az adatok entitásábrázolását, és végül visszaadja az entitást számunkra.

Belsőleg az Ülés nyomon követi az összes entitást, amelyet a tartós kontextustárolóba tölt. Esetünkben a A munkamenet a belső tároló 3 entitást tartalmaz a lekérdezés után.

Most változtassuk meg Gigi nevét:

Tranzakciós tranzakció = session.getTransaction (); ügylet.begin (); FootballPlayer gigiBuffon = players.stream () .filter (p -> p.getId () == 3) .findFirst () .get (); gigiBuffon.setName ("Gianluigi Buffon"); ügylet.vállalás (); assertThat (getDirtyEntities ()). size (). isEqualTo (1); assertThat (getDirtyEntities (). get (0) .getName ()). isEqualTo ("Gianluigi Buffon");

4.1. Hogyan működik?

Tranzakcióra híváskor elkövetni() vagy öblítés (), a Ülés talál bármelyiket piszkos entitásokat a nyomon követési listájáról, és szinkronizálja az állapotot az adatbázissal.

Figyelje meg, hogy semmilyen módszert nem kellett hívnunk az értesítéshez Ülés hogy valamit megváltoztattunk az entitásunkban - mivel ez egy felügyelt entitás, minden változás automatikusan továbbkerül az adatbázisba.

A kezelt entitás mindig állandó entitás - rendelkeznie kell adatbázis-azonosítóval, annak ellenére, hogy az adatbázis-sor ábrázolása még nincs létrehozva, vagyis az INSERT utasítás a munkaegység végére vár.

Lásd az alábbiakban az átmeneti entitásokról szóló fejezetet.

5. Leválasztott entitás

A levált entitás csak egy rendes entitás POJO amelynek azonosító értéke megfelel egy adatbázis-sornak. A különbség a kezelt entitástól abban van senki sem követi tovább kitartás összefüggései.

Az entitás akkor válhat le, amikor a Ülés betöltésére használt volt zárva, vagy amikor hívunk Session.evict (entitás) vagy Session.clear ().

Lássuk a kódban:

FootballPlayer cr7 = session.get (FootballPlayer.class, 1L); assertThat (getManagedEntities (munkamenet)). size (). isEqualTo (1); assertThat (getManagedEntities (session) .get (0) .getId ()). isEqualTo (cr7.getId ()); session.evict (cr7); assertThat (getManagedEntities (munkamenet)). size (). isEqualTo (0);

Perzisztencia-kontextusunk nem fogja követni a levált entitások változását:

cr7.setName ("CR7"); ügylet.vállalás (); assertThat (getDirtyEntities ()). isEmpty ();

Session.merge (entitás) /Session.update (entitás) tud (újból csatolja a munkamenetet:

FootballPlayer messi = session.get (FootballPlayer.class, 2L); session.evict (messi); messi.setName ("Leo Messi"); ügylet.vállalás (); assertThat (getDirtyEntities ()). isEmpty (); tranzakció = startTransaction (munkamenet); session.update (messi); ügylet.vállalás (); assertThat (getDirtyEntities ()). size (). isEqualTo (1); assertThat (getDirtyEntities (). get (0) .getName ()). isEqualTo ("Leo Messi");

Referenciaként mindkettőre Session.merge () és Session.update () lásd itt.

5.1. Az identitás mező minden fontos

Vessünk egy pillantást a következő logikára:

FootballPlayer gigi = new FootballPlayer (); gigi.setId (3); gigi.setName ("Gigi a legenda"); session.update (gigi);

A fenti példában egy entitást a szokásos módon példányosítottunk konstruktorán keresztül. A mezőket értékekkel töltöttük fel, és az identitást 3-ra állítottuk, ami megfelel a Gigi Buffonhoz tartozó állandó adatok azonosságának. Hívás frissítés () pontosan ugyanolyan hatást gyakorol, mintha az entitást egy másikból töltöttük volna be kitartás összefüggései.

Valójában, Ülés nem különbözteti meg, honnan származik egy újracsatolt entitás.

A webalkalmazásokban meglehetősen gyakori forgatókönyv a leválasztott entitások HTML űrlapértékekből történő összeállítására.

Addig, amíg Ülés vonatkozik, a leválasztott entitás csak egy sima entitás, amelynek azonosító értéke megfelel a tartós adatoknak.

Ne feledje, hogy a fenti példa csak egy bemutató célt szolgál. és pontosan tudnunk kell, mit csinálunk. Ellenkező esetben az egész entitásunkban nullértékek születhetnek, ha csak beállítjuk az értéket a frissíteni kívánt mezőre, a többit érintetlenül hagyjuk (tehát gyakorlatilag nullát).

6. Átmeneti entitás

A tranziens entitás egyszerűen egy entitás olyan objektum, amelynek nincs ábrázolása a tartós tárolóban és nem kezeli senki Ülés.

A tranziens entitás tipikus példája egy új entitás példányosítása a konstruktora révén.

Átmeneti entitás létrehozására kitartó, telefonálnunk kell Session.save (entitás) vagy Session.saveOrUpdate (entitás):

FootballPlayer neymar = új FootballPlayer (); neymar.setName ("Neymar"); session.save (neymar); assertThat (getManagedEntities (munkamenet)). size (). isEqualTo (1); assertThat (neymar.getId ()). nemNull (); int count = queryCount ("válassza ki a count (*) értéket a Football_Playerből, ahol name =" Neymar ""); assertThat (count) .isEqualTo (0); ügylet.vállalás (); count = queryCount ("select count (*) from Football_Player ahol name =" Neymar ""); assertThat (count) .isEqualTo (1);

Amint kivégezzük Session.save (entitás), az entitáshoz identitásértéket rendelnek, és a Ülés. Előfordulhat azonban, hogy még nem áll rendelkezésre az adatbázisban, mivel az INSERT művelet késhet a munkaegység végéig.

7. Törölt entitás

Az entitás törölt (eltávolított) állapotban van, ha Session.delete (entitás) hívták, és a Ülés megjelölte az entitást törlésre. Maga a DELETE parancs kiadható a munkaegység végén.

Lássuk a következő kódban:

session.delete (neymar); assertThat (getManagedEntities (session) .get (0) .getStatus ()). isEqualTo (Status.DELETED);

Azonban vegye figyelembe, hogy az entitás a munkaegység végéig a tartós környezetben marad.

8. Következtetés

A koncepció kitartás összefüggései központi szerepet játszik a hibernált entitások életciklusának megértésében. Pontosítottuk az életciklust az egyes állapotokat bemutató kódpéldák megvizsgálásával.

Szokás szerint az ebben a cikkben használt kód megtalálható a GitHubon.


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