Objektumállapotok a Hibernate munkamenetében

1. Bemutatkozás

A hibernálás kényelmes keretrendszer a perzisztens adatok kezeléséhez, de a belső működés megértése időnként bonyolult lehet.

Ebben az oktatóanyagban megismerhetjük az objektum állapotokat és az azok közötti mozgást. Megvizsgáljuk azokat a problémákat is, amelyekkel az elszakadt entitásokkal találkozhatunk, és azok megoldását.

2. Hibernate-munkamenet

A Ülés Az interfész a Hibernate-tel való kommunikáció fő eszköze. API-t biztosít, amely lehetővé teszi számunkra a tartós objektumok létrehozását, olvasását, frissítését és törlését. A ülés életciklusa egyszerű. Kinyitjuk, végrehajtunk néhány műveletet, majd bezárjuk.

Amikor a tárgyakat megoperáljuk a ülés, ehhez kötődnek ülés. Az elvégzett változásokat a záráskor észleljük és elmentjük. A bezárás után a hibernálás megszakítja az objektumok és a munkamenet közötti kapcsolatokat.

3. Objektumállapotok

A hibernátus kontextusában Ülés, az objektumok a három lehetséges állapot egyikében lehetnek: átmeneti, tartósak vagy leváltak.

3.1. Átmeneti

Olyan tárgy, amelyet nem csatoltunk egyikhez sem ülés átmeneti állapotban van. Mivel soha nem volt kitartó, ezért nincs ábrázolva az adatbázisban. Mert nem ülés tisztában van vele, nem menti automatikusan.

Hozzunk létre egy felhasználói objektumot a konstruktorral, és erősítsük meg, hogy azt nem a munkamenet kezeli:

Munkamenet = openSession (); UserEntity userEntity = új UserEntity ("John"); assertThat (session.contains (userEntity)). isFalse ();

3.2. Kitartó

Egy objektum, amelyet társítottunk a ülés tartós állapotban van. Vagy elmentettük, vagy egy perzisztencia-kontextusból olvastuk, így ez képviseli az adatbázis valamelyik sorát.

Hozzunk létre egy objektumot, majd használjuk a kitartani módszer, hogy tartós legyen:

Munkamenet = openSession (); UserEntity userEntity = new UserEntity ("John"); session.persist (userEntity); assertThat (session.contains (userEntity)). isTrue ();

Alternatív megoldásként használhatjuk a mentés módszer. A különbség az, hogy a kitartani metódus csak menteni egy objektumot, és a mentés metódus emellett generálja az azonosítóját, ha erre szükség van.

3.3. Különálló

Amikor bezárjuk a ülés, a benne lévő összes tárgy leválik. Bár továbbra is az adatbázisban lévő sorokat képviselik, már senki sem kezeli őket ülés:

session.persist (userEntity); session.close (); assertThat (session.isOpen ()). isFalse (); assertThatThrownBy (() -> session.contains (userEntity));

Ezután megtanuljuk, hogyan kell menteni a tranziens és leválasztott entitásokat.

4. Entitás mentése és újracsatolása

4.1. Átmeneti entitás mentése

Hozzunk létre egy új entitást, és mentse el az adatbázisba. Amikor először elkészítjük az objektumot, akkor átmeneti állapotban lesz.

Nak nek kitartani új entitásunk, akkor a kitartani módszer:

UserEntity userEntity = new UserEntity ("John"); session.persist (userEntity);

Most létrehozunk egy másik objektumot, azonos azonosítóval, mint az első. Ez a második objektum átmeneti, mert még senki sem kezeli ülés, de nem tudjuk kitartóvá tenni a kitartani módszer. Már szerepel az adatbázisban, tehát nem igazán új a perzisztencia réteg összefüggésében.

Helyette, használjuk a összeolvad módszer az adatbázis frissítésére és az objektum tartóssá tételére:

UserEntity onceAgainJohn = új UserEntity ("John"); session.merge (OnceAgainJohn);

4.2. Leválasztott entitás mentése

Ha bezárjuk az előzőt ülés, tárgyaink leszakadt állapotban lesznek. Az előző példához hasonlóan az adatbázisban is szerepelnek, de jelenleg egyikük sem kezeli őket ülés. Újra kitartóvá tehetjük őket a összeolvad módszer:

UserEntity userEntity = új UserEntity ("John"); session.persist (userEntity); session.close (); session.merge (userEntity);

5. Beágyazott entitások

A dolgok bonyolultabbá válnak, ha figyelembe vesszük a beágyazott entitásokat. Tegyük fel, hogy felhasználói entitásunk a kezelőjéről is információkat tárol:

public class UserEntity {@Id private String név; @ManyToOne privát UserEntity manager; }

Amikor mentjük ezt az entitást, nemcsak az entitás állapotára kell gondolnunk, hanem a beágyazott entitás állapotára is. Hozzunk létre egy állandó felhasználói entitást, majd állítsuk be a kezelőjét:

UserEntity userEntity = új UserEntity ("John"); session.persist (userEntity); UserEntity manager = új UserEntity ("Adam"); userEntity.setManager (kezelő);

Ha most megpróbáljuk frissíteni, kivételt kapunk:

assertThatThrownBy (() -> {session.saveOrUpdate (userEntity); tranzakció.vállalkozás ();});
java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: az objektum nem mentett átmeneti példányra hivatkozik - mentsük el az átmeneti példányt az öblítés előtt: com.baeldung.states.UserEntity.manager -> com.baeldung.states.UserEntity 

Ez azért történik, mert a Hibernate nem tud mit kezdeni az átmeneti beágyazott entitással.

5.1. Megmaradt beágyazott entitások

A probléma megoldásának egyik módja a beágyazott entitások kifejezett fennmaradása:

UserEntity manager = új UserEntity ("Adam"); munkamenet.ellenőr (menedzser); userEntity.setManager (kezelő);

Ezután a tranzakció végrehajtása után lekérhetjük a helyesen mentett entitást:

ügylet.vállalás (); session.close (); Session otherSession = openSession (); UserEntity savedUser = otherSession.get (UserEntity.class, "John"); assertThat (savedUser.getManager (). getName ()). isEqualTo ("Adam");

5.2. Lépcsőzetes műveletek

Az átmeneti beágyazott entitások automatikusan fennmaradhatnak, ha konfiguráljuk a kapcsolatot vízesés tulajdonság az entitásosztályban helyesen:

@ManyToOne (cascade = CascadeType.PERSIST) privát UserEntity manager;

Most, amikor továbbra is fennáll az objektum, a művelet minden beágyazott entitáshoz sor kerül:

UserEntityWithCascade userEntity = új UserEntityWithCascade ("John"); session.persist (userEntity); UserEntityWithCascade manager = új UserEntityWithCascade ("Adam"); userEntity.setManager (kezelő); // tranziens menedzser hozzáadása a tartós felhasználói munkamenethez.saveOrUpdate (userEntity); ügylet.vállalás (); session.close (); Session otherSession = openSession (); UserEntityWithCascade savedUser = otherSession.get (UserEntityWithCascade.class, "John"); assertThat (savedUser.getManager (). getName ()). isEqualTo ("Adam");

6. Összefoglalás

Ebben az oktatóanyagban közelebbről megvizsgáltuk a hibernálás módját Ülés az objektum állapota szempontjából működik. Ezután megvizsgáltunk néhány problémát, amelyet ez okozhat, és azok megoldását.

Mint mindig, a forráskód is elérhető a GitHubon.