מדריך ל- SqlResultSetMapping

1. הקדמה

במדריך זה נסתכל על SqlResultSetMapping, מחוץ ל- Java Persistence API (JPA).

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

2. התקנה

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

2.1. תלות של Maven

התלות הנדרשת שלנו ב- Maven הם Hibernate ו- H2 Database. Hibernate נותן לנו את היישום של מפרט ה- JPA. אנו משתמשים במסד H2 עבור מסד נתונים בזיכרון.

2.2. מאגר מידע

לאחר מכן ניצור שתי טבלאות כפי שנראה כאן:

צור עובד שכיר (id BIGINT, שם VARCHAR (10));

ה עוֹבֵד שולחנות מאחסן תוצאה אחת יֵשׁוּת לְהִתְנַגֵד. SCHEDULE_DAYS מכיל רשומות המקושרות ל- עוֹבֵד טבלה לפי העמודה תג עובד:

צור לוח SCHEDULE_DAYS (מזהה מזהה, עובדId BIGINT, dayOfWeek VARCHAR (10));

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

2.3. אובייקטים של ישויות

שֶׁלָנוּ יֵשׁוּת חפצים צריכים להיראות דומים:

עובד בכיתה ציבורית @Entity {@ Id פרטי מזהה ארוך; שם מחרוזת פרטי; }

יֵשׁוּת ניתן לקרוא לאובייקטים באופן שונה מטבלאות מסדי נתונים. נוכל להוסיף הערות לשיעור באמצעות @שולחן למפות אותם במפורש:

@Entity @Table (name = "SCHEDULE_DAYS") מחזור ציבורי מתוזמן יום {@ Id @ GeneratedValue פרטי מזהה ארוך; פרטי LongId עובד; יום מחרוזת פרטי; }

3. מיפוי סקלרים

עכשיו שיש לנו נתונים אנחנו יכולים להתחיל למפות תוצאות שאילתות.

3.1. ColumnResult

בזמן SqlResultSetMapping ו שאילתא הערות עובדות על מאגר בשיעורים, אנו משתמשים בהערות על יֵשׁוּת בכיתה בדוגמה זו.

כֹּל SqlResultSetMapping ביאור דורש נכס אחד בלבד, שֵׁם. עם זאת, ללא אחד מסוגי החברים, שום דבר לא ימופה. סוגי החברים הם ColumnResult, ConstructorResult, ו EntityResult.

במקרה הזה, ColumnResult ממפה כל עמודה לסוג תוצאה סקלרי:

@SqlResultSetMapping (name = "FridayEmployeeResult", עמודות = {@ ColumnResult (name = "עובדId")})

ה ColumnResult תכונה שֵׁם מזהה את העמודה בשאילתה שלנו:

@NamedNativeQuery (name = "FridayEmployees", query = "בחר עובדId FROM לוח הזמנים WHERE dayOfWeek = 'FRIDAY'", resultSetMapping = "FridayEmployeeResult") 

ציין זאת הערך של resultSetMapping בשלנו NamedNativeQuery ביאור חשוב מכיוון שהוא תואם את שֵׁם נכס משלנו ResultSetMapping הַצהָרָה.

כתוצאה מכך, NamedNativeQuery קבוצת התוצאות ממופה כצפוי. כְּמוֹ כֵן, StoredProcedure API דורש שיוך זה.

3.2. ColumnResult מִבְחָן

נצטרך כמה אובייקטים ספציפיים למצב שינה כדי להריץ את הקוד שלנו:

@BeforeAll הגדרת חלל סטטי ציבורית () {emFactory = Persistence.createEntityManagerFactory ("java-jpa-dags-מתוזמן"); em = emFactory.createEntityManager (); }

לבסוף, אנו קוראים לשאילתה שצוינה כדי להריץ את הבדיקה שלנו:

@ מבחן ציבורי בטל כאשר NameQuery_thenColumnResult () {רשימה עובדIds = em.createNamedQuery ("יום שישי עובדים"). GetResultList (); assertEquals (2, employeeIds.size ()); }

4. מיפוי קונסטרוקטורים

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

4.1. ConstructorResult

באופן דומה לשלנו ColumnResult לדוגמא, נוסיף את SqlResultMapping ביאור על שלנו יֵשׁוּת מעמד, מתוזמן יום. עם זאת, על מנת למפות באמצעות קונסטרוקטור, עלינו ליצור אחד:

Public ScheduledDay (מזהה ארוך, עובד ארוך, שעת שלמה, שעת מספר שלמה, מחרוזת של שבוע) {this.id = id; this.employeeId = עובדId; this.dayOfWeek = dayofWeek; }

כמו כן, המיפוי מציין את מחלקת היעד ואת העמודות (שניהם נדרשים):

@SqlResultSetMapping (name = "ScheduleResult", classes = {@ConstructorResult (targetClass = com.baeldung.sqlresultsetmapping.ScheduledDay.class, columns = {@ColumnResult (name = "id", type = Long.class), @ColumnResult (name = "עובדId", סוג = Long.class), @ColumnResult (name = "dayOfWeek")})})

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

@NamedNativeQuery (name = "Schedules", query = "SELECT * FROM לוח הזמנים WHERE עובדId = 8", resultSetMapping = "ScheduleResult")

הבדל ייחודי נוסף עבור ConstructorResult הוא כי האינסטינציה של האובייקט המתקבלת היא כ"חדשה "או" מנותקת ". הממופה יֵשׁוּת יהיה במצב מנותק כאשר קיים מפתח ראשי תואם ב- EntityManager אחרת זה יהיה חדש.

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

4.2. ConstructorResult מִבְחָן

בואו נבדוק את ConstructorResult במבחן יחידה:

@ מבחן פומבי בטל כאשר NameQuery_thenConstructorResult () {רשימה schedDays = Collections.checkedList (em.createNamedQuery ("לוחות זמנים", ScheduledDay.class) .getResultList (), ClassedDay.class); assertEquals (3, scheduleDays.size ()); assertTrue (schedulDays.stream (). allMatch (c -> c.getEmployeeId (). longValue () == 3)); }

5. מיפוי ישויות

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

5.1. ישות יחידה

EntityResult מחייב אותנו לציין את מחלקת הישות, עוֹבֵד. אנו משתמשים באופציה שדות נכס לשליטה רבה יותר. משולב עם FieldResult, אנו יכולים למפות כינויים ושדות שאינם תואמים:

@SqlResultSetMapping (name = "EmployeeResult", entities = {@EntityResult (entityClass = com.baeldung.sqlresultsetmapping.Employee.class, fields = {@FieldResult (name = "id", column = "employeeNumber"), @FieldResult (name = "שם", עמודה = "שם")}}})

כעת השאילתה שלנו צריכה לכלול את העמודה המופעלת:

@NamedNativeQuery (name = "עובדים", שאילתה = "בחר מזהה כמו עובד מספר, שם FROM EMPLOYEE", resultSetMapping = "EmployeeResult")

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

5.2. ישויות מרובות

מיפוי ישויות מרובות הוא די פשוט לאחר שמיפינו ישות אחת:

@SqlResultSetMapping (name = "EmployeeScheduleResults", entities = {@EntityResult (entityClass = com.baeldung.sqlresultsetmapping.Employee.class), @EntityResult (entityClass = com.baeldung.sqlresultsetmapping.ScheduledDay.class)

5.3. EntityResult בדיקות

בואו נסתכל על EntityResult בִּפְעוּלָה:

@ מבחן ציבורי בטל כאשר NameQuery_thenSingleEntityResult () {רשימת עובדים = Collections.checkedList (em.createNamedQuery ("עובדים"). GetResultList (), שכיר עובד); assertEquals (3, workers.size ()); assertTrue (workers.stream (). allMatch (c -> c.getClass () == שכיר עובד)); }

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

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

@Test ציבורי בטל כאשר NameQuery_thenMultipleEntityResult () {Query query = em.createNativeQuery ("בחר e.id, e.name, d.id, d.employeeId, d.dayOfWeek" + "FROM עובד e, לוח זמנים של ימי" d "+" WHERE e .id = d. EmployeeId "," EmployeeScheduleResults "); תוצאות רשימה = query.getResultList (); assertEquals (4, results.size ()); assertTrue (results.get (0) .length == 2); עובד עובד = (עובד) results.get (1) [0]; יום ScheduledDay = תוצאות (ScheduledDay). Get (1) [1]; assertTrue (day.getEmployeeId () == emp.getId ()); }

6. מסקנה

במדריך זה בדקנו אפשרויות שונות לשימוש ב- SqlResultSetMapping ביאור. SqlResultSetMapping הוא חלק מרכזי בממשק ה- API של Java Persistence.

ניתן למצוא קטעי קוד ב- GitHub.


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