נעילה אופטימית ב- JPA

1. הקדמה

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

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

כדי להשיג זאת נוכל להשתמש במנגנון נעילה אופטימי המסופק על ידי Java Persistence API. זה מוביל כי עדכונים מרובים שבוצעו באותם נתונים בו זמנית אינם מפריעים זה לזה.

2. הבנת נעילה אופטימית

על מנת להשתמש בנעילה אופטימית, עלינו להיות עם ישות הכוללת נכס @גִרְסָה ביאור. בזמן השימוש בה, כל עסקה שקוראת נתונים מחזיקה את ערך מאפיין הגרסה.

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

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

3. נעילה פסימית לעומת נעילה אופטימית

טוב לדעת שבניגוד לנעילה אופטימית JPA נותן לנו נעילה פסימית. זהו מנגנון נוסף לטיפול בגישה בו זמנית לנתונים.

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

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

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

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

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

4. תכונות גרסה

תכונות גרסה הן מאפיינים עם @גִרְסָה ביאור. הם נחוצים לאפשר נעילה אופטימית. בואו נראה מחלקת ישויות לדוגמא:

סטודנט בכיתה ציבורית @Entity {@Id פרטי מזהה ארוך; שם מחרוזת פרטי; שם משפחה פרטי מחרוזת; גרסת @Version פרטית שלמה; // גטרים וקובעים}

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

  • על כל מחלקת ישויות לכלול מאפיין גרסה אחד בלבד
  • יש למקם אותו בטבלה הראשית עבור ישות הממופה למספר טבלאות
  • סוג מאפיין הגרסה חייב להיות אחד מהבאים: int, מספר שלם, ארוך, ארוך, קצר, קצר, java.sql. חותמת זמן

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

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

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

5. נעילת מצבים

JPA מספק לנו שני מצבי נעילה אופטימיים שונים (ושני כינויים):

  • אוֹפּטִימִי - הוא משיג נעילת קריאה אופטימית לכל הגופים המכילים תכונת גרסה
  • OPTIMISTIC_FORCE_INCREMENT - זה משיג נעילה אופטימית כמו אוֹפּטִימִי ובנוסף מגדיל את ערך תכונת הגרסה
  • לקרוא - זו מילה נרדפת ל- אוֹפּטִימִי
  • לִכתוֹב - זו מילה נרדפת ל- OPTIMISTIC_FORCE_INCREMENT

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

5.1. אוֹפּטִימִי (לקרוא)

כידוע, אוֹפּטִימִי ו לקרוא מצבי נעילה הם מילים נרדפות. עם זאת, מפרט JPA ממליץ לנו להשתמש אוֹפּטִימִי ביישומים חדשים.

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

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

  • עודכן או נמחק אך לא התחייב
  • בינתיים עודכן או נמחק בהצלחה

5.2. OPTIMISTIC_INCREMENT (לִכתוֹב)

אותו דבר כמו בעבר, OPTIMISTIC_INCREMENT ו לִכתוֹב הם מילים נרדפות, אך הראשונים עדיפים.

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

כדאי לדעת כי ספק התמדה רשאי לספק OPTIMISTIC_INCREMENT פונקציונליות מתי אוֹפּטִימִי נדרש מצב נעילה.

6. שימוש בנעילה אופטימית

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

6.1. למצוא

כדי לבקש נעילה אופטימית נוכל לעבור את התקין LockModeType כטיעון למצוא שיטה של EntityManager:

entityManager.find (Student.class, studentId, LockModeType.OPTIMISTIC);

6.2. שאילתא

דרך נוספת לאפשר נעילה היא שימוש ב- setLockMode שיטה של שאילתא לְהִתְנַגֵד:

שאילתת שאילתה = entityManager.createQuery ("מ- Student where id =: id"); query.setParameter ("id", studentId); query.setLockMode (LockModeType.OPTIMISTIC_INCREMENT); query.getResultList ()

6.3. נעילה מפורשת

אנו יכולים לנעול באמצעות התקשרות ל- EnitityManager לנעול שיטה:

סטודנט סטודנט = entityManager.find (Student.class, id); entityManager.lock (סטודנט, LockModeType.OPTIMISTIC);

6.4. לְרַעֲנֵן

אנחנו יכולים להתקשר ל לְרַעֲנֵן שיטה באותו אופן כמו השיטה הקודמת:

סטודנט סטודנט = entityManager.find (Student.class, id); entityManager.refresh (סטודנט, LockModeType.READ);

6.5. NamedQuery

האפשרות האחרונה היא להשתמש ב- @ NameQuery עם ה- מצב נעילה תכונה:

@NamedQuery (name = "optimisticLock", השאילתה = "בחר S מתוך תלמיד s WHERE s.id LIKE: id", lockMode = WRITE)

7. OptimisticLockException

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

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

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

8. מסקנה

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

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

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

עובדה נוספת שעלינו לזכור היא שבכל פעם שיש עדכונים סותרים על ישויות, עלינו לצפות ל OptimisticLockException.

לבסוף, קוד המקור של הדרכה זו זמין ב- GitHub.