תחזיות JPA JPA

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

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

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

2. הגדרה ראשונית

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

2.1. תלות Maven

לקבלת תלות, אנא עיין בסעיף 2 במדריך זה.

2.2. שיעורי ישויות

בואו נגדיר שתי מחלקות ישויות:

כתובת @ class בכיתה ציבורית {@ Id פרטי מזהה ארוך; אדם אדם פרטי @OneToOne; מדינת מיתרים פרטית; עיר מיתרים פרטית; רחוב מיתרים פרטי; פרטי מחרוזת zipCode; // גטרים וקובעים}

וגם:

אדם בכיתה ציבורית @Entity {@Id פרטי מזהה ארוך; פרטי מחרוזת firstName; שם משפחה פרטי מחרוזת; @OneToOne (mappedBy = "אדם") כתובת כתובת פרטית; // גטרים וקובעים}

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

שימו לב במדריך זה, אנו משתמשים במסד נתונים משובץ - H2.

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

2.3. סקריפטים של SQL

אנו משתמשים ב- השלכה-הוספה-נתונים.שקל סקריפט לאכלוס שתי טבלאות הגיבוי:

הכנס לאדם (מזהה, שם פרטי, שם משפחה) VALUES (1, 'John', 'Doe'); הכנס לכתובת (מזהה, person_id, מדינה, עיר, רחוב, מיקוד) ערכים (1,1, 'CA', 'לוס אנג'לס', 'Standford Ave', '90001');

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

מחק מהכתובת; מחק מאדם;

2.4. כיתת מבחן

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

@DataJpaTest @RunWith (SpringRunner.class) @Sql (scripts = "/projection-insert-data.sql") @Sql (scripts = "/projection-clean-up-data.sql", executionPhase = AFTER_TEST_METHOD) JpaProjectionIntegration בכיתה ציבורית {// שדות מוזרקים ושיטות בדיקה}

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

3. תחזיות מבוססות ממשק

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

3.1. תחזיות סגורות

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

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

ממשק ציבורי AddressView {String getZipCode (); }

ואז השתמש בו בממשק מאגר:

ממשק ציבורי AddressRepository מרחיב מאגר {List getAddressByState (מצב מחרוזת); }

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

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

בואו נעשה בדיקה מהירה של ה- כתובת הַקרָנָה:

@Autowired פרטי AddressRepository addressRepository; @ מבחן ציבורי בטל כאשר משתמש ClosedProjections_thenViewWithRequiredPropertiesIsReturned () {AddressView addressView = addressRepository.getAddressByState ("CA"). Get (0); assertThat (addressView.getZipCode ()). isEqualTo ("90001"); // ...}

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

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

ממשק ציבורי PersonView {String getFirstName (); מחרוזת getLastName (); }

עכשיו, בואו נוסיף שיטה עם סוג ההחזרה PersonView - השלכה מקוננת - ב כתובת הַקרָנָה:

ממשק ציבורי AddressView {// ... PersonView getPerson (); }

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

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

// ... PersonView personView = addressView.getPerson (); assertThat (personView.getFirstName ()). isEqualTo ("ג'ון"); assertThat (personView.getLastName ()). isEqualTo ("איילה");

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

3.2. תחזיות פתוחות

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

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

בוא נחזור ל אדם ממשק הקרנה והוסף שיטה חדשה:

ממשק ציבורי PersonView {// ... @Value ("# {target.firstName + '' + target.lastName}") מחרוזת getFullName (); }

הטיעון ל @ערך ביאור הוא ביטוי SpEL, שבו ה- יַעַד מעצב מציין את אובייקט ישות הגיבוי.

כעת נגדיר ממשק מאגר אחר:

ממשק ציבורי PersonRepository מאריך מאגר {PersonView findByLastName (שם מחרוזת); }

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

מבחן זה מאשר את עבודות התחזיות הפתוחות כצפוי:

@ איש אישי אישי מאגר אישי מאגר; @Testpublic בטל כאשרUsingOpenProjections_thenViewWithRequiredPropertiesIsReturned () {PersonView personView = personRepository.findByLastName ("איילה"); assertThat (personView.getFullName ()). isEqualTo ("ג'ון דו"); }

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

4. תחזיות כיתתיות

במקום להשתמש ב- proxies Spring Data יוצר עבורנו מממשקי הקרנה, אנו יכולים להגדיר שיעורי הקרנה משלנו.

לדוגמה, הנה שיעור הקרנה עבור אדם יֵשׁוּת:

ClassD PersonDto {שם פרטי פרטי מחרוזת; שם משפחה פרטי מחרוזת; PersonDto public (שם מחרוזת, שם משפחה מחרוזת) {this.firstName = שם פרטי; this.lastName = lastname; } // getters, שווה ו- hashCode}

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

עלינו גם להגדיר שווים ו hashCode יישומים - הם מאפשרים ל- Spring Data לעבד חפצי הקרנה באוסף.

עכשיו, בואו נוסיף שיטה ל- אדם מאגר:

ממשק ציבורי PersonRepository מרחיב מאגר {// ... PersonDto findByFirstName (שם מחרוזת); }

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

@ מבחן ציבורי בטל כאשר UsClassBasedProjections_thenDtoWithRequiredPropertiesIsReturned () {PersonDto personDto = personRepository.findByFirstName ("John"); assertThat (personDto.getFirstName ()). isEqualTo ("ג'ון"); assertThat (personDto.getLastName ()). isEqualTo ("איילה"); }

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

5. תחזיות דינמיות

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

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

אנו יכולים ליישם תחזיות דינמיות רק על ידי הכרזת שיטת מאגר עם מעמד פָּרָמֶטֶר:

ממשק ציבורי PersonRepository מרחיב מאגר {// ... T findByLastName (שם מחרוזת, סוג מחלקה); }

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

@ מבחן ציבורי בטל כאשר משתמש DynamicProjections_thenObjectWithRequiredPropertiesIsReturned () {Person person = personRepository.findByLastName ("Doe", Person.class); PersonView personView = personRepository.findByLastName ("איילה", PersonView.class); PersonDto personDto = personRepository.findByLastName ("איילה", PersonDto.class); assertThat (person.getFirstName ()). isEqualTo ("ג'ון"); assertThat (personView.getFirstName ()). isEqualTo ("ג'ון"); assertThat (personDto.getFirstName ()). isEqualTo ("ג'ון"); }

6. מסקנה

במאמר זה, עברנו על סוגים שונים של תחזיות Spring Data JPA.

קוד המקור של הדרכה זו זמין ב- GitHub. זהו פרויקט של Maven ואמור להיות מסוגל לרוץ כמו שהוא.


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