מחזור חיים של ישות במצב שינה

1. סקירה כללית

באופן טבעי יש לכל ישות שינה מחזור חיים במסגרת - הוא נמצא במצב חולף, מנוהל, מנותק או שנמחק.

הבנת מצבים אלה ברמה הרעיונית והטכנית היא חיונית כדי להיות מסוגלים להשתמש בתרדמת שינה בצורה נכונה.

כדי ללמוד על שיטות שינה שונות העוסקות בישויות, עיין באחת מההדרכות הקודמות שלנו.

2. שיטות עוזר

במהלך הדרכה זו נשתמש בעקביות בכמה שיטות עוזרות:

  • HibernateLifecycleUtil.getManagedEntities (הפעלה) - נשתמש בו כדי להשיג את כל הגופים המנוהלים מ- מושבים חנות פנימית
  • DirtyDataInspector.getDirtyEntities () - אנו נשתמש בשיטה זו כדי לקבל רשימה של כל הגופים שסומנו כ"מלוכלכים "
  • HibernateLifecycleUtil.queryCount (שאילתה) - שיטה נוחה לעשות לספור(*) שאילתה כנגד מסד הנתונים המשובץ

כל שיטות העזר לעיל מיובאות באופן סטטי לקריאות טובה יותר. תוכל למצוא את היישומים שלהם בפרויקט GitHub המקושר בסוף מאמר זה.

3. הכל על הקשר ההתמדה

לפני שנכנס לנושא מחזור החיים של הישות, ראשית, עלינו להבין הקשר ההתמדה.

במילים פשוטות, ה הקשר התמדה יושב בין קוד לקוח לחנות נתונים. זהו אזור בימוי שבו מומרים נתונים מתמשכים ליישויות, מוכנים לקריאה ולשינוי באמצעות קוד לקוח.

באופן תיאורטי, ה הקשר התמדה הוא יישום של דפוס יחידת העבודה. הוא עוקב אחר כל הנתונים הטעונים, עוקב אחר שינויים של נתונים אלה, ואחראי לסנכרן בסופו של דבר כל שינוי בחזרה למסד הנתונים בתום העסקה העסקית.

JPA EntityManager ושל תרדמת החורף מוֹשָׁב הם יישום של הקשר התמדה מוּשָׂג. במהלך מאמר זה נשתמש במצב שינה מוֹשָׁב לייצג הקשר התמדה.

מצב מחזור החיים של ישות בתרדמת מסביר כיצד ישות קשורה ל- הקשר התמדה, כפי שנראה בהמשך.

4. ישות מנוהלת

ישות מנוהלת היא ייצוג של שורה בטבלת מסדי נתונים (למרות ששורה זו עדיין לא חייבת להתקיים במסד הנתונים).

זה מנוהל על ידי הפועל כרגע מוֹשָׁב, ו כל שינוי שנעשה בו יעקוב ויופץ למסד הנתונים באופן אוטומטי.

ה מוֹשָׁב או טוען את הישות ממסד הנתונים או מצרף מחדש ישות מנותקת. נדון בגופים מנותקים בסעיף 5.

בואו נצפה בקוד כלשהו כדי לקבל הבהרה.

היישום לדוגמה שלנו מגדיר ישות אחת, ה- שחקן כדורגל מעמד. בעת ההפעלה, אנו מאותחלים את מאגר הנתונים בכמה נתוני דוגמה:

+ ------------------- + ------- + | שם | תעודת זהות | + ------------------- + ------- + | כריסטיאנו רונאלדו | 1 | | ליונל מסי | 2 | | ג'אנלואיג'י בופון | 3 | + ------------------- + ------- +

בואו נגיד שאנחנו רוצים לשנות את שמו של בופון מלכתחילה - אנחנו רוצים להכניס את שמו המלא ג'אנלואיג'י בופון במקום ג'יג'י בופון.

ראשית, עלינו להתחיל את יחידת העבודה שלנו באמצעות השגת a מוֹשָׁב:

מושב מושב = sessionFactory.openSession ();

בסביבת שרתים, אנו עשויים להזרים a מוֹשָׁב לקוד שלנו באמצעות פרוקסי מודע להקשר. העיקרון נשאר זהה: אנחנו צריכים a מוֹשָׁב כדי לתמצת את העסקה העסקית של יחידת העבודה שלנו.

לאחר מכן, ננחה את שלנו מוֹשָׁב לטעינת הנתונים מהחנות המתמשכת:

assertThat (getManagedEntities (הפעלה)). הוא ריק (); רשימת שחקנים = s.createQuery ("מ- FootballPlayer"). GetResultList (); assertThat (getManagedEntities (session)). size (). isEqualTo (3); 

כשאנחנו מקבלים לראשונה א מוֹשָׁב, חנות ההקשרים המתמשכת שלה ריקה, כפי שמראה הראשון שלנו לִטעוֹן הַצהָרָה.

לאחר מכן אנו מבצעים שאילתה השואבת נתונים ממסד הנתונים, יוצרת ייצוג ישויות של הנתונים ולבסוף מחזירה את היישות לשימושנו.

באופן פנימי, מוֹשָׁב עוקב אחר כל הגופים שהוא טוען בחנות ההקשר המתמיד. במקרה שלנו, מושבים חנות פנימית תכיל 3 ישויות לאחר השאילתה.

עכשיו בואו נשנה את שמו של ג'יג'י:

עסקת עסקה = session.getTransaction (); transaction.begin (); FootballPlayer gigiBuffon = players.stream () .filter (p -> p.getId () == 3) .findFirst () .get (); gigiBuffon.setName ("ג'אנלואיג'י בופון"); transaction.commit (); assertThat (getDirtyEntities ()). size (). isEqualTo (1); assertThat (getDirtyEntities (). get (0) .getName ()). isEqualTo ("ג'אנלואיג'י בופון");

4.1. איך זה עובד?

בקריאה לעסקה לְבַצֵעַ() אוֹ סומק(), ה מוֹשָׁב ימצא כל אחד מְלוּכלָך ישויות מרשימת המעקב שלה ומסנכרן את המדינה למסד הנתונים.

שימו לב שלא היינו צריכים להתקשר לשום שיטה שתודיע מוֹשָׁב ששינינו משהו ביישות שלנו - מכיוון שמדובר ביישות מנוהלת, כל השינויים מועברים למסד הנתונים באופן אוטומטי.

ישות מנוהלת היא תמיד ישות קבועה - עליה להיות בעלת מזהה מסד נתונים, למרות שייצוג שורת מסד הנתונים טרם נוצר, כלומר משפט INSERT ממתין לסיום יחידת העבודה.

ראה פרק אודות ישויות חולפות להלן.

5. ישות תלושה

א ישות מנותקת הוא פשוט ישות רגילה POJO שערך הזהות שלו תואם לשורת מסד נתונים. ההבדל מגוף מנוהל הוא שזהו לא עוקב אחר על ידי אף אחד הקשר התמדה.

ישות יכולה להתנתק כאשר ה- מוֹשָׁב נהג לטעון את זה היה סגור, או כשאנחנו מתקשרים Session.evict (ישות) אוֹ Session.clear ().

בואו נראה את זה בקוד:

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

הקשר ההתמדה שלנו לא יעקוב אחר השינויים בגופים מנותקים:

cr7.setName ("CR7"); transaction.commit (); assertThat (getDirtyEntities ()). isEmpty ();

Session.merge (ישות) / Session.update (ישות) יכול (צירף מחדש מושב):

FootballPlayer messi = session.get (FootballPlayer.class, 2L); session.evict (messi); messi.setName ("ליאו מסי"); transaction.commit (); assertThat (getDirtyEntities ()). isEmpty (); עסקה = startTransaction (הפעלה); session.update (messi); transaction.commit (); assertThat (getDirtyEntities ()). size (). isEqualTo (1); assertThat (getDirtyEntities (). get (0) .getName ()). isEqualTo ("ליאו מסי");

להתייחסות על שניהם Session.merge () ו Session.update () ראה כאן.

5.1. תחום הזהות הוא כל מה שחשוב

בואו נסתכל על ההיגיון הבא:

FootballPlayer gigi = FootballPlayer חדש (); gigi.setId (3); gigi.setName ("ג'יג'י האגדה"); session.update (ג'יג'י);

בדוגמה שלמעלה ייצרנו ישות בדרך הרגילה באמצעות הבנאי שלה. אכלסנו את השדות בערכים והגדרנו את הזהות ל- 3, שמתאימה לזהות הנתונים המתמידים השייכים לג'יג'י בופון. יִעוּד עדכון() משפיעה בדיוק על אותה השפעה כאילו העמסנו את הישות מאחר הקשר התמדה.

למעשה, מוֹשָׁב אינו מבחין מאיפה מקור ישות מחוברת מחדש.

זה תרחיש מקובל למדי ביישומי אינטרנט לבניית ישויות מנותקות מערכי טופס HTML.

כל עוד מוֹשָׁב מודאג, ישות מנותקת היא רק יישות רגילה שערך זהותה תואם נתונים קבועים.

שים לב שהדוגמה שלמעלה רק משרתת מטרת הדגמה. ואנחנו צריכים לדעת בדיוק מה אנחנו עושים. אחרת, אנו עשויים לקבל ערכי אפס בכל היישות שלנו אם רק נקבע את הערך בשדה אותו אנו רוצים לעדכן ונשאיר את השאר ללא פגע (כך למעשה אפס).

6. ישות חולפת

ישות חולפת היא פשוט יֵשׁוּת אובייקט שאין לו ייצוג בחנות המתמשכת ולא מנוהל על ידי אף אחד מוֹשָׁב.

דוגמה אופיינית ליישות חולפת תהיה יצירת ישות חדשה באמצעות הבנאי שלה.

ליצור ישות חולפת מַתְמִיד, אנחנו צריכים להתקשר Session.save (ישות) אוֹ Session.saveOrUpdate (ישות):

FootballPlayer neymar = חדש FootballPlayer (); neymar.setName ("Neymar"); session.save (neymar); assertThat (getManagedEntities (session)). size (). isEqualTo (1); assertThat (neymar.getId ()). isNotNull (); int count = queryCount ("בחר ספירה (*) מ- Football_Player כאשר שם =" Neymar ""); assertThat (count) .isEqualTo (0); transaction.commit (); count = queryCount ("בחר ספירה (*) מ- Football_Player שם name =" Neymar ""); assertThat (count) .isEqualTo (1);

ברגע שאנחנו מבצעים Session.save (ישות), לישות מוקצה ערך זהות והופך להיות מנוהל על ידי מוֹשָׁב. עם זאת, ייתכן שהוא עדיין לא יהיה זמין במסד הנתונים מכיוון שפעולת INSERT עשויה להתעכב עד לסיום יחידת העבודה.

7. יישות שנמחקה

ישות נמצאת במצב שנמחק (הוסר) אם Session.delete (ישות) נקרא, ו מוֹשָׁב סימן את הישות למחיקה. הפקודה DELETE עצמה עשויה להיות מונפקת בסוף יחידת העבודה.

בואו נראה את זה בקוד הבא:

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

עם זאת, שים לב שהישות נשארת בחנות ההקשר המתמיד עד לסיום יחידת העבודה.

8. מסקנה

הקונספט של הקשר התמדה הוא מרכזי בהבנת מחזור החיים של ישויות שינה. הבהרנו את מחזור החיים על ידי בחינת דוגמאות הקוד המדגימות כל סטטוס.

כרגיל, ניתן למצוא את הקוד המשמש במאמר זה ב- GitHub.


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