מדריך שינה אחד להרבה הערות

1. הקדמה

מדריך שינה מהיר זה יביא אותנו דרך דוגמה של אחד לרבים מיפוי באמצעות הערות JPA, חלופה ל- XML.

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

2. תיאור

פשוט שים,אחד לרבים מיפוי פירושו ששורה אחת בטבלה ממופה למספר שורות בטבלה אחרת.

בואו נסתכל על הדיאגרמה הבאה של יחסי ישות כדי לראות a אחד לרבים אִרגוּן:

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

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

הדרך בה אנו עושים זאת בקוד היא עם @אחד לרבים.

בואו למפות את עֲגָלָה כיתה ל פריטים חפץ באופן המשקף את הקשר במסד הנתונים:

עגלה בכיתה ציבורית {// ... @OneToMany (mappedBy = "cart") פריטי סט פרטיים; // ...}

אנחנו יכולים גם להוסיף התייחסות ל עֲגָלָה ב פריטים באמצעות @ManyToOne, מה שהופך את זה למערכת יחסים דו כיוונית. דו כיווני פירושו זה אנו יכולים לגשת פריטים מ עגלות, וגם עגלות מ פריטים.

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

הטכנולוגיות והספריות הבאות משמשות במטרה לפתח יישום לדוגמא של מצב שינה אחד לרבים אִרגוּן:

  • JDK 1.8 ואילך
  • שינה 5
  • Maven 3 ואילך
  • מסד נתונים H2

3. התקנה

3.1. הגדרת מסד נתונים

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

צור טבלה 'עגלה' ('cart_id` int (11) לא חתומה NOT NULL AUTO_INCREMENT, PRIMARY KEY (`cart_id`)) MOTOR = InnoDB AUTO_INCREMENT = 5 CHARSET DEFAULT = utf8; צור טבלה "פריטים" ("id" int (11) לא חתום לא NULL AUTO_INCREMENT, "cart_id" int (11) unsigned NOT NULL, PRIMARY KEY ("id"), KEY "cart_id" ("cart_id"), CONSTRAINT "items_ibfk_1 `מפתח חוץ (` cart_id`) הפניות `עגלה` (` cart_id`)) מנוע = InnoDB AUTO_INCREMENT = 7 CHARSET Default = utf8;

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

3.2. תלות Maven

לאחר מכן נוסיף את תלות הנהג Hibernate ו- H2 pom.xml קוֹבֶץ. התלות בתרדמת שינה משתמשת ברישום JBoss, והיא מתווספת אוטומטית כתלות מעבר:

  • גרסת שינה 5.2.7 גמר
  • גרסת הנהג H2 1.4.197

אנא בקר במאגר המרכזי של Maven לגירסאות העדכניות ביותר של Hibernate ותלות H2.

3.3. תצורת שינה

הנה התצורה של מצב שינה:

  org.h2.Driver jdbc: h2: mem: spring_hibernate_one_to_many sa org.hibernate.dialect.H2Dialect true 

3.4. HibernateAnnotationUtil מעמד

עם ה HibernateAnnotationUtil בכיתה, עלינו רק להפנות לקובץ התצורה החדש של מצב שינה:

פרטית סטטית SessionFactory sessionFactory; פרטי SessionFactory buildSessionFactory () {ServiceRegistry serviceRegistry = חדש StandardServiceRegistryBuilder (). הגדר ("hibernate-annotation.cfg.xml"). build (); מטא-נתונים מטא-נתונים = MetadataSources חדשים (serviceRegistry) .getMetadataBuilder (). Build (); SessionFactory sessionFactory = metadata.getSessionFactoryBuilder (). Build (); מפגש חזרה מפעל; } ציבורי SessionFactory getSessionFactory () {if (sessionFactory == null) sessionFactory = buildSessionFactory (); מפגש חזרה מפעל; }

4. הדוגמניות

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

@Entity @Table (name = "CART") עגלת מחלקה ציבורית {// ... @OneToMany (mappedBy = "cart") פריטי סט פרטי; // גטרים וקובעים}

שים לב כי @אחד לרבים הערה משמשת להגדרת המאפיין ב- פריטים מחלקה שתשמש למיפוי ממופה על ידי מִשְׁתַנֶה. לכן יש לנו נכס בשם "עֲגָלָה" בתוך ה פריטים מעמד:

@Entity @Table (name = "ITEMS") מחלקה ציבורית פריטים {// ... @ManyToOne @JoinColumn (name = "cart_id", nullable = false) עגלת עגלה פרטית; פריטים ציבוריים () {} // getters and setters} 

חשוב גם לציין כי @ManyToOne ההערה קשורה ל- עֲגָלָה משתנה כיתתי. @JoinColumn ביאור מפנה את העמודה הממופה.

5. בפעולה

בתוכנית הבדיקה אנו יוצרים שיעור עם א רָאשִׁי() שיטה לקבלת מושב שינה, ושמירת אובייקטים מודל לתוך מסד הנתונים ליישום ה- אחד לרבים אִרגוּן:

sessionFactory = HibernateAnnotationUtil.getSessionFactory (); session = sessionFactory.getCurrentSession (); System.out.println ("מושב נוצר"); tx = session.beginTransaction (); session.save (עגלה); session.save (item1); session.save (item2); tx.commit (); System.out.println ("Cartitem1, מפתח זר Cartitem2, מפתח זר זר הרבה לאחד">6. ה @ManyToOne ביאור

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

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

6.1. חוסר עקביות ובעלות

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

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

בואו נדמיין מצב שבו מפתח רוצה להוסיף פריט 1 ל עֲגָלָה ו פריט 2 ל עגלה 2, אבל עושה טעות כך שההפניות בין עגלה 2 ו פריט 2 להיות לא עקבי:

עגלת עגלה 1 = עגלה חדשה (); עגלת עגלה 2 = עגלה חדשה (); פריטים item1 = פריטים חדשים (cart1); פריטים item2 = פריטים חדשים (cart2); Set itemsSet = חדש HashSet (); itemsSet.add (item1); itemsSet.add (item2); cart1.setItems (itemsSet); // שגוי!

כפי שמוצג לעיל, פריט 2 הפניות cart2, ואילו עגלה 2 לא מתייחס פריט 2, וזה רע.

איך צריך לחסוך במצב שינה פריט 2 למסד הנתונים? רָצוֹן פריט 2 התייחסות למפתח זר עגלה 1 אוֹ עגלה 2?

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

6.2. פריטים כצד הבעלים

כאמור במפרט JPA בסעיף 2.9, זה נוהג טוב לסמן רבים לאחד צד כצד בעלים.

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

אז איך השגנו זאת?

על ידי הכללת ה- ממופה על ידי תכונה ב עֲגָלָה בכיתה, אנו מסמנים זאת כצד ההפוך.

במקביל, אנו מציינים גם את ה- פריטים.עֲגָלָה שדה עם @ManyToOne, עושה פריטים הצד שבבעלות.

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

בואו נבדוק את התוצאה:

מזהה פריט 1 = 1, מזהה עגלת מפתח זר = 1 פריט 2 מזהה = 2, מזהה עגלת מפתח זר = 2

למרות ש עֲגָלָה הפניות פריט 2 בקטע שלנו, פריט 2התייחסות ל עגלה 2 נשמר במסד הנתונים.

6.3. עֲגָלָה כצד הבעלים

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

למרות שזה לא נוהג מומלץ, בואו וננסה.

קטע הקוד שלמטה מציג את היישום של אחד לרבים הצד כצד הבעלים:

מחלקה ציבורית ItemsOIO {// ... @ManyToOne @JoinColumn (name = "cart_id", insertable = false, update = false) עגלת CartOIO פרטית; // ..} מחלקה ציבורית CartOIO {// .. @OneToMany @JoinColumn (name = "cart_id") // עלינו לשכפל את המידע הפיזי של קבוצות פרטיות; // ..} 

שימו לב כיצד הסרנו את ממופה על ידי אלמנט וקבע את רבים לאחד @JoinColumn כפי ש נָעִיץ ו ניתן לעדכן ל שֶׁקֶר.

אם נפעיל את אותו קוד, התוצאה תהיה הפוכה:

מזהה פריט 1 = 1, מזהה עגלת מפתח זרה = פריט 2 מזהה = 2, מזהה עגלת מפתח זר = 1

כפי שמוצג לעיל, עכשיו פריט 2 שייך ל עֲגָלָה.

7. מסקנה

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

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

קוד המקור במאמר זה ניתן למצוא באתר GitHub.