התנגדות למדינות במושב שינה

1. הקדמה

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

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

2. מושב שינה

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

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

3. מדינות אובייקט

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

3.1. חולף

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

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

מושב מושב = openSession (); UserEntity userEntity = UserEntity חדש ("ג'ון"); assertThat (session.contains (userEntity)). isFalse ();

3.2. מַתְמִיד

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

בואו ניצור אובייקט ואז נשתמש ב- להתמיד שיטה להפוך את זה למתמשך:

מושב מושב = openSession (); UserEntity userEntity = UserEntity חדש ("ג'ון"); session.persist (userEntity); assertThat (session.contains (userEntity)). isTrue ();

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

3.3. מְנוּתָק

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

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

לאחר מכן נלמד כיצד לשמור על ישויות חולפות ומנותקות.

4. שמירה והצמדת ישות מחדש

4.1. שמירת ישות חולפת

בואו ניצור ישות חדשה ונשמור אותה במסד הנתונים. כשאנחנו בונים לראשונה את האובייקט, הוא יהיה במצב חולף.

ל להתמיד היישות החדשה שלנו, נשתמש ב- להתמיד שיטה:

UserEntity userEntity = UserEntity חדש ("ג'ון"); session.persist (userEntity);

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

במקום זאת, נשתמש ב- לְמַזֵג שיטה לעדכן את מסד הנתונים ולהפוך את האובייקט למתמשך:

UserEntity onceAgainJohn = UserEntity חדש ("ג'ון"); session.merge (onceAgainJohn);

4.2. שמירת ישות תלושה

אם נסגור את הקודם מוֹשָׁב, האובייקטים שלנו יהיו במצב מנותק. בדומה לדוגמא הקודמת, הם מיוצגים במסד הנתונים, אך הם אינם מנוהלים כרגע על ידי אף אחד מוֹשָׁב. אנו יכולים לגרום להם להתמיד שוב באמצעות לְמַזֵג שיטה:

UserEntity userEntity = UserEntity חדש ("ג'ון"); session.persist (userEntity); session.close (); session.merge (userEntity);

5. ישויות מקוננות

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

מחלקת ציבור UserEntity {@Id פרטי מחרוזת; @ManyToOne מנהל UserEntity פרטי; }

כאשר אנו שומרים את הישות הזו, עלינו לחשוב לא רק על מצב הישות עצמה אלא גם על מצב הישות המקוננת. בואו ניצור ישות משתמשים קבועה ואז נקבע את המנהל שלה:

UserEntity userEntity = UserEntity חדש ("ג'ון"); session.persist (userEntity); מנהל UserEntity = UserEntity חדש ("אדם"); userEntity.setManager (מנהל);

אם ננסה לעדכן אותו כעת, נקבל חריג:

assertThatThrownBy (() -> {session.saveOrUpdate (userEntity); transaction.commit ();});
java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: אובייקט מפנה למופע חולף שלא נשמר - שמור את המופע החולף לפני שטיפה: com.baeldung.states.UserEntity.manager -> com.baeldung.states.UserEntity 

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

5.1. ישויות מקוננות מתמשכות

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

מנהל UserEntity = UserEntity חדש ("אדם"); session.persist (מנהל); userEntity.setManager (מנהל);

לאחר מכן, לאחר ביצוע העסקה, נוכל לאחזר את הישות שנשמרה כהלכה:

transaction.commit (); session.close (); מושב otherSession = openSession (); UserEntity savedUser = otherSession.get (UserEntity.class, "John"); assertThat (savedUser.getManager (). getName ()). isEqualTo ("אדם");

5.2. מבצעים מדורגים

ניתן לשמור על ישויות מקוננות חולפות באופן אוטומטי אם אנו מגדירים את היחסים אֶשֶׁד נכס כהלכה במחלקת הישויות:

@ManyToOne (מפל = CascadeType.PERSIST) מנהל UserEntity פרטי;

כעת כאשר אנו ממשיכים להתמודד עם האובייקט, פעולה זו תשלף לכל הישויות המקוננות:

UserEntityWithCascade userEntity = UserEntityWithCascade חדש ("ג'ון"); session.persist (userEntity); UserEntityWithCascade manager = UserEntityWithCascade חדש ("אדם"); userEntity.setManager (מנהל); // הוסף מנהל חולף לסשן משתמשים מתמשך.saveOrUpdate (userEntity); transaction.commit (); session.close (); מושב otherSession = openSession (); UserEntityWithCascade savedUser = otherSession.get (UserEntityWithCascade.class, "ג'ון"); assertThat (savedUser.getManager (). getName ()). isEqualTo ("אדם");

6. סיכום

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

כמו תמיד, קוד המקור זמין ב- GitHub.


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