מיפוי עם אוריקה

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

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

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

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

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

2. דוגמה פשוטה

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

אנו יוצרים a MapperFactory חפץ כך:

MapperFactory mapperFactory = DefaultMapperFactory.Builder חדש (). Build ();

ואז בהנחה שיש לנו אובייקט נתוני מקור, Source.java, עם שני שדות:

מחלקה ציבורית מקור {שם מחרוזת פרטי; גיל פרטי פרטי; מקור ציבורי (שם מחרוזת, גיל int) {this.name = name; this.age = גיל; } // גטרים וקובעים סטנדרטיים}

ואובייקט נתוני יעד דומה, Dest.java:

מחלקה ציבורית Dest {שם פרטי מחרוזת; גיל פרטי פרטי; ציבורי Dest (שם מחרוזת, int גיל) {this.name = שם; this.age = גיל; } // גטרים וקובעים סטנדרטיים}

זהו הבסיסי ביותר במיפוי שעועית באמצעות אוריקה:

@Test ציבור בטל givenSrcAndDest_whenMaps_thenCorrect () {mapperFactory.classMap (Source.class, Dest.class); MapperFacade mapper = mapperFactory.getMapperFacade (); מקור src = מקור חדש ("Baeldung", 10); Dest dest = mapper.map (src, Dest.class); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

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

@Test הציבור בטל givenSrcAndDest_whenMapsReverse_thenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .byDefault (); MapperFacade mapper = mapperFactory.getMapperFacade (); Dest src = Dest חדש ("Baeldung", 10); מקור יעד = mapper.map (src, Source.class); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

3. הגדרת Maven

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

 ma.glasnost.orika אוריקה-ליבה 1.4.6 

הגרסה האחרונה תמיד נמצאת כאן.

3. עבודה עם MapperFactory

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

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

3.1. ה BoundMapperFacade לעומת MapperFacade

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

המבחן הראשוני שלנו יהפוך לפיכך ל:

@Test הציבור בטל givenSrcAndDest_whenMapsUsingBoundMapper_thenCorrect () {BoundMapperFacade boundMapper = mapperFactory.getMapperFacade (Source.class, Dest.class); מקור src = מקור חדש ("baeldung", 10); Dest dest = boundMapper.map (src); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

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

@Test הציבור בטל givenSrcAndDest_whenMapsUsingBoundMapperInReverse_thenCorrect () {BoundMapperFacade boundMapper = mapperFactory.getMapperFacade (Source.class, Dest.class); Dest src = Dest חדש ("baeldung", 10); מקור dest = boundMapper.mapReverse (src); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

המבחן ייכשל אחרת.

3.2. הגדר הגדרות מיפוי שדות

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

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

אדם בכיתה ציבורית {פרטי שם מחרוזת; כינוי מחרוזת פרטי; גיל פרטי פרטי; אדם ציבורי (שם מחרוזת, כינוי מחרוזת, גיל int) {this.name = name; this.nickname = כינוי; this.age = גיל; } // גטרים וקובעים סטנדרטיים}

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

מעמד ציבורי אישי {פרטי מחרוזת מחרוזת; פרטי מחרוזת מחרוזת; גיל פרטי פרטי; פרסונאי ציבורי (מחרוזת, מחרוזת, מחרוזת, גיל) {this.nom = nom; this.surnom = surnom; this.age = גיל; } // גטרים וקובעים סטנדרטיים}

אוריקה לא יכולה לפתור אוטומטית את ההבדלים הללו. אבל אנחנו יכולים להשתמש ב- ClassMapBuilder ממשק API לרישום מיפויים ייחודיים אלה.

כבר השתמשנו בו בעבר, אך עדיין לא ניצלנו אף אחד מהתכונות החזקות שלו. השורה הראשונה של כל אחד מהבדיקות הקודמות שלנו משתמשת כברירת המחדל MapperFacade השתמש ב- ClassMapBuilder API לרישום שתי המחלקות שרצינו למפות:

mapperFactory.classMap (Source.class, Dest.class);

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

mapperFactory.classMap (Source.class, Dest.class) .byDefault ()

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

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

@Test הציבור בטל שניתןSrcAndDestWithDifferentFieldNames_whenMaps_thenCorrect () {mapperFactory.classMap (Personne.class, Person.class) .field ("nom", "name"). שדה ("surnom", "כינוי"). שדה ("גיל", " גיל "). רישום (); MapperFacade mapper = mapperFactory.getMapperFacade (); Personne frenchPerson = Personne חדש ("קלייר", "cla", 25); אדם אנגליתפרסון = mapper.map (צרפתיתפרסון, Person.class); assertEquals (englishPerson.getName (), frenchPerson.getNom ()); assertEquals (englishPerson.getNickname (), frenchPerson.getSurnom ()); assertEquals (englishPerson.getAge (), frenchPerson.getAge ()); }

אל תשכח להתקשר ל להירשם() שיטת API על מנת לרשום את התצורה עם ה- MapperFactory.

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

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

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

mapperFactory.classMap (Personne.class, Person.class) .field ("nom", "name"). field ("surnom", "nickname"). byDefault (). register ();

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

3.3. אל תכלול שדה

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

@Test הציבור בטל שניתןSrcAndDest_whenCanExcludeField_thenCorrect () {mapperFactory.classMap (Personne.class, Person.class) .exclude ("nom") .field ("surnom", "nickname"). שדה ("גיל", "גיל"). להירשם(); MapperFacade mapper = mapperFactory.getMapperFacade (); Personne frenchPerson = Personne חדש ("קלייר", "cla", 25); אדם אנגליתפרסון = mapper.map (צרפתיתפרסון, Person.class); assertEquals (null, englishPerson.getName ()); assertEquals (englishPerson.getNickname (), frenchPerson.getSurnom ()); assertEquals (englishPerson.getAge (), frenchPerson.getAge ()); }

שימו לב כיצד אנו לא כוללים את זה בתצורת ה- MapperFactory ואז שימו לב גם לקביעה הראשונה שבה אנו מצפים לערך של שֵׁם בתוך ה אדם התנגד להישאר ריק, כתוצאה מכך שהוא לא נכלל במיפוי.

4. מיפוי אוספים

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

4.1. רשימות ומערכים

שקול אובייקט נתוני מקור שיש לו רק שדה אחד, רשימה של שמות האדם:

מחלקה ציבורית PersonNameList {name name listlist; PersonNameList ציבורי (List nameList) {this.nameList = nameList; }}

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

מחלקה ציבורית PersonNameParts {פרטי מחרוזת firstName; שם משפחה פרטי מחרוזת; PersonNameParts ציבורי (שם מחרוזת, שם משפחה מחרוזת) {this.firstName = firstName; this.lastName = lastname; }}

נניח שאנחנו בטוחים מאוד שבמדד 0 תמיד יהיה ה שם פרטי של האדם ובאינדקס 1 תמיד יהיו שלהם שם משפחה.

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

@Test הציבור בטל givenSrcWithListAndDestWithPrimitiveAttributes_whenMaps_thenCorrect () {mapperFactory.classMap (PersonNameList.class, PersonNameParts.class) .field ("nameList [0]", "firstName"). שדה ("nameList [1]", "שם אחרון." (); MapperFacade mapper = mapperFactory.getMapperFacade (); רשימת nameList = Arrays.asList (מחרוזת חדשה [] {"סילבסטר", "סטאלון"}); PersonNameList src = PersonpersonList חדש (nameList); PersonNameParts dest = mapper.map (src, PersonNameParts.class); assertEquals (dest.getFirstName (), "סילבסטר"); assertEquals (dest.getLastName (), "סטאלון"); }

גם אם במקום PersonNameList, היה לנו PersonNameArray, אותו מבחן יעבור למערך שמות.

4.2. מפות

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

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

מחלקה ציבורית PersonNameMap {Map name name Map; פומבי PersonNameMap (Map nameMap) {this.nameMap = nameMap; }}

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

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

@Test הציבור בטל givenSrcWithMapAndDestWithPrimitiveAttributes_whenMaps_thenCorrect () {mapperFactory.classMap (PersonNameMap.class, PersonNameParts.class) .field ("nameMap ['first']", "firstName") .field ("nameMap [\" last \ ") "שם משפחה") .register (); MapperFacade mapper = mapperFactory.getMapperFacade (); Map nameMap = HashMap חדש (); nameMap.put ("ראשון", "ליורנאדו"); nameMap.put ("אחרון", "DiCaprio"); PersonNameMap src = חדש PersonNameMap (nameMap); PersonNameParts dest = mapper.map (src, PersonNameParts.class); assertEquals (dest.getFirstName (), "Leornado"); assertEquals (dest.getLastName (), "DiCaprio"); }

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

5. מפה שדות מקוננים

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

מחלקה ציבורית PersonContainer {שם פרטי; PersonContainer ציבורי (שם שם) {this.name = שם; }}
מחלקה ציבורית שם {פרטי מחרוזת שם פרטי; שם משפחה פרטי מחרוזת; שם ציבורי (שם מחרוזת, שם משפחה מחרוזת) {this.firstName = שם פרטי; this.lastName = lastname; }}

כדי להיות מסוגל לגשת למאפיינים של ה- DTO המקונן ולמפות אותם אל אובייקט היעד שלנו, אנו משתמשים בסימון נקודות, כך:

@Test ציבורי בטל givenSrcWithNestedFields_whenMaps_thenCorrect () {mapperFactory.classMap (PersonContainer.class, PersonNameParts.class) .field ("name.firstName", "firstName") .field ("name.lastName", "lastname"). Register () ; MapperFacade mapper = mapperFactory.getMapperFacade (); PersonContainer src = PersonContainer חדש (שם חדש ("ניק", "קנון")); PersonNameParts dest = mapper.map (src, PersonNameParts.class); assertEquals (dest.getFirstName (), "ניק"); assertEquals (dest.getLastName (), "Canon"); }

6. מיפוי ערכים אפסיים

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

@Test ציבור בטל givenSrcWithNullField_whenMapsThenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .byDefault (); MapperFacade mapper = mapperFactory.getMapperFacade (); מקור src = מקור חדש (null, 10); Dest dest = mapper.map (src, Dest.class); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

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

6.1. תצורה גלובלית

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

MapperFactory mapperFactory = חדש DefaultMapperFactory.Builder () .mapNulls (false) .build ();

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

@Test הציבור בטל givenSrcWithNullAndGlobalConfigForNoNull_whenFailsToMap_ThenCorrect () {mapperFactory.classMap (Source.class, Dest.class); MapperFacade mapper = mapperFactory.getMapperFacade (); מקור src = מקור חדש (null, 10); Dest dest = חדש Dest ("קלינטון", 55); mapper.map (src, dest); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), "קלינטון"); }

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

במקרה שלנו, שדה היעד אינו מוחלף אם לשדה המקור המקביל שלו יש ריק ערך.

6.2. תצורה מקומית

מיפוי של ריק ניתן לשלוט בערכים על ClassMapBuilder באמצעות mapNulls (נכון | שקר) אוֹ mapNullsInReverse (נכון | שקר) לשליטה במיפוי אפסים בכיוון ההפוך.

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

בואו נמחיש זאת במבחן לדוגמא:

@Test הציבור בטל שניתןSrcWithNullAndLocalConfigForNoNull_whenFailsToMap_ThenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .field ("age", "age") .mapNulls (false). שדה ("שם", "שם"). ).להירשם(); MapperFacade mapper = mapperFactory.getMapperFacade (); מקור src = מקור חדש (null, 10); Dest dest = חדש Dest ("קלינטון", 55); mapper.map (src, dest); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), "קלינטון"); }

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

מיפוי דו-כיווני מקבל גם ערכי null ממופים:

@Test הציבור בטל givenDestWithNullReverseMappedToSource_whenMapsByDefault_thenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .byDefault (); MapperFacade mapper = mapperFactory.getMapperFacade (); Dest src = Dest חדש (null, 10); מקור יעד = מקור חדש ("Vin", 44); mapper.map (src, dest); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

כמו כן אנו יכולים למנוע זאת על ידי התקשרות mapNullsInReverse ועובר פנימה שֶׁקֶר:

@Test ציבורי בטל שניתןDestWithNullReverseMappedToSourceAndLocalConfigForNoNull_whenFailsToMap_thenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .field ("age", "age") .mapNullsInReverse (")." שם (")." ) .להירשם(); MapperFacade mapper = mapperFactory.getMapperFacade (); Dest src = Dest חדש (null, 10); מקור יעד = מקור חדש ("Vin", 44); mapper.map (src, dest); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), "Vin"); }

6.3. תצורת רמת שדה

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

mapperFactory.classMap (Source.class, Dest.class) .field ("age", "age") .fieldMap ("name", "name"). mapNulls (false) .add (). byDefault (). register ( );

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

@Test הציבור בטל שניתןSrcWithNullAndFieldLevelConfigForNoNull_whenFailsToMap_ThenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .field ("age", "age") .fieldMap ("name", "name"). Mapaddulls (false). ) .byDefault (). register (); MapperFacade mapper = mapperFactory.getMapperFacade (); מקור src = מקור חדש (null, 10); Dest dest = חדש Dest ("קלינטון", 55); mapper.map (src, dest); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), "קלינטון"); }

7. מיפוי מותאם אישית של אוריקה

עד כה בדקנו דוגמאות פשוטות למיפוי מותאם אישית באמצעות ClassMapBuilder ממשק API. אנו עדיין נשתמש באותו API אך נתאים אישית את המיפוי שלנו באמצעות Orika CustomMapper מעמד.

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

אובייקט נתונים אחד מייצג ערך זה כ- מחרוזת זמן בפורמט ISO הבא:

2007-06-26T21: 22: 39Z

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

1182882159000

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

הבה ניצור את אובייקט הנתונים הראשון שלנו:

מחלקה ציבורית אדם 3 {פרטי מחרוזת; פרטי מחרוזת dtob; אדם אישי 3 (שם מחרוזת, מחרוזת dtob) {this.name = שם; this.dtob = dtob; }}

ואז אובייקט הנתונים השני שלנו:

מחלקה ציבורית Personne3 {שם מחרוזת פרטי; dtob פרטי פרטי; Personne3 ציבורי (שם מחרוזת, dtob ארוך) {this.name = שם; this.dtob = dtob; }}

לא נסמן איזה מקור ואיזה יעד כרגע הוא CustomMapper מאפשר לנו לספק מיפוי דו כיווני.

הנה היישום הקונקרטי שלנו של ה- CustomMapper שיעור מופשט:

class PersonCustomMapper מרחיב את CustomMapper {@Override public void mapAtoB (Personne3 a, Person3 b, MappingContext context) {תאריך תאריך = תאריך חדש (a.getDtob ()); פורמט DateFormat = SimpleDateFormat חדש ("yyyy-MM-dd'T'HH: mm: ss'Z '"); מחרוזת isoDate = format.format (תאריך); b.setDtob (isoDate); } @ עקוף מפה בטוחה ציבורית BtoA (Person3 b, Personne3 a, MappingContext context) {DateFormat format = new SimpleDateFormat ("yyyy-MM-dd'T'HH: mm: ss'Z '"); תאריך תאריך = format.parse (b.getDtob ()); חותמת זמן ארוכה = date.getTime (); a.setDtob (חותמת זמן); }};

שימו לב שהטמענו שיטות mapAtoB ו mapBtoA. יישום שניהם גורם לתפקוד המיפוי שלנו להיות דו כיווני.

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

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

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

@Test הציבור בטל givenSrcAndDest_whenCustomMapperWorks_thenCorrect () {mapperFactory.classMap (Personne3.class, Person3.class) .customize (customMapper) .register (); MapperFacade mapper = mapperFactory.getMapperFacade (); מחרוזת תאריך זמן = "2006-06-26T21: 22: 39Z"; חותמת זמן ארוכה = New Long ("1182882159000"); Personne3 personne3 = Personne3 חדש ("Leornardo", חותמת זמן); Person3 person3 = mapper.map (personne3, Person3.class); assertEquals (person3.getDtob (), dateTime); }

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

אנו יכולים לאשר גם כי מיפוי דו-כיווני עובד:

@Test הציבור בטל givenSrcAndDest_whenCustomMapperWorksBidirectionally_thenCorrect () {mapperFactory.classMap (Personne3.class, Person3.class) .customize (customMapper) .register (); MapperFacade mapper = mapperFactory.getMapperFacade (); מחרוזת תאריך זמן = "2006-06-26T21: 22: 39Z"; חותמת זמן ארוכה = New Long ("1182882159000"); Person3 person3 = Person3 חדש ("Leornardo", dateTime); Personne3 personne3 = mapper.map (person3, Personne3.class); assertEquals (person3.getDtob (), חותמת זמן); }

8. מסקנה

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

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

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


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