קשר אחד לאחד ב- JPA

1. הקדמה

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

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

2. תיאור

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

זו דוגמה ליחסים בין אחד לאחד, במקרה הזה בין מִשׁתַמֵשׁ ו כתובת ישויות.

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

3. שימוש במפתח זר

3.1. דוגמנות עם מפתח זר

בואו נסתכל על דיאגרמת ה- ER הבאה המייצגת מיפוי אחד לאחד על בסיס מפתח זר:

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

3.2. יישום עם מפתח זר ב- JPA

ראשית, בואו ניצור את מִשׁתַמֵשׁ כיתב והערה עליו כראוי:

@Entity @Table (name = "משתמשים") משתמש בכיתה ציבורית {@Id @GeneratedValue (אסטרטגיה = GenerationType.AUTO) @Column (name = "id") פרטי מזהה ארוך; // ... @OneToOne (cascade = CascadeType.ALL) @JoinColumn (name = "address_id", referencedColumnName = "id") כתובת כתובת פרטית; // ... גטרים וקובעים} 

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

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

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

ה כתובת היישות מתבררת קצת יותר פשוטה:

@Entity @Table (name = "address") כתובת ציבורית {@Id @GeneratedValue (אסטרטגיה = GenerationType.AUTO) @Column (name = "id") פרטי מזהה ארוך; // ... @OneToOne (mappedBy = "address") משתמש פרטי פרטי; // ... גטרים וקובעים}

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

4. שימוש במפתח ראשי משותף

4.1. דוגמנות עם מפתח ראשי משותף

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

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

4.2. יישום עם מפתח ראשי משותף ב- JPA

שימו לב שההגדרות שלנו משתנות רק מעט:

@Entity @Table (name = "משתמשים") משתמש בכיתה ציבורית {@Id @GeneratedValue (אסטרטגיה = GenerationType.AUTO) @Column (name = "id") פרטי מזהה ארוך; // ... @OneToOne (mappedBy = "user", cascade = CascadeType.ALL) @PrimaryKeyJoinColumn כתובת כתובת פרטית; // ... גטרים וקובעים}
@Entity @Table (name = "address") מחלקה ציבורית כתובת {@ Id @Column (name = "user_id") פרטי מזהה ארוך; // ... @OneToOne @MapsId @JoinColumn (name = "user_id") משתמש פרטי פרטי; // ... גטרים וקובעים} 

ה ממופה על ידי התכונה מועברת כעת אל מִשׁתַמֵשׁ כיוון שהמפתח הזר קיים כעת ב- כתובת שולחן. הוספנו גם ה @PrimaryKeyJoinColumn ביאור, המציין כי המפתח הראשי של ה- מִשׁתַמֵשׁ הישות משמשת כערך המפתח הזר עבור המשויך כתובת יֵשׁוּת.

עלינו עדיין להגדיר @תְעוּדַת זֶהוּת שדה ב כתובת בכיתה אך שימו לב זה מתייחס ל תעודת זהות של משתמש העמודה, והיא כבר לא משתמשת ב @ GeneratedValue ביאור. כמו כן, על השדה המתייחס ל מִשׁתַמֵשׁ, הוספנו ה @MapsId ביאור, המציין כי ערכי המפתח העיקריים יועתקו מ ה מִשׁתַמֵשׁ יֵשׁוּת.

5. שימוש בטבלת הצטרפות

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

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

5.1. דוגמנות עם שולחן הצטרפות

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

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

עכשיו, בכל פעם שיש לנו מערכת יחסים, נרשום ערך ב- emp_workstation טבלה והימנע מאפסיםלְגַמרֵי.

5.2. יישום באמצעות שולחן הצטרפות ב- JPA

נעשה שימוש בדוגמה הראשונה שלנו @JoinColumn. הפעם נשתמש @JoinTable:

@Entity @Table (name = "עובד") שכבה ציבורית עובד {@ Id @ GeneratedValue (אסטרטגיה = GenerationType.AUTO) @ עמודה (name = "id") פרטי מזהה ארוך; // ... @OneToOne (cascade = CascadeType.ALL) @JoinTable (name = "emp_workstation", joinColumn = {@JoinColumn (name = "עובד_איד", referensColumnName = "id")}, הפוך = "workstation_id", referencedColumnName = "id")}) WorkStation workstation פרטי; // ... גטרים וקובעים}
@Entity @Table (name = "תחנת עבודה") Workstation בכיתה ציבורית {@Id @GeneratedValue (אסטרטגיה = GenerationType.AUTO) @Column (name = "id") מזהה ארוך פרטי; // ... @OneToOne (mappedBy = "workStation") עובד שכיר פרטי; // ... גטרים וקובעים}

@הצטרף לטבלה מורה למצב שינה לממש את אסטרטגיית שולחן ההצטרפות תוך שמירה על הקשר.

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

6. מסקנה

במדריך זה למדנו דרכים שונות לשמור על עמותה אחת לאחד ב- JPA ו- Hibernate ומתי להשתמש בכל אחת מהן.

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