Térképezés Orikával

1. Áttekintés

Az Orika egy Java Bean térképészeti keretrendszer, amely rekurzívan másolja az adatokat az egyik objektumból a másikba. Nagyon hasznos lehet többrétegű alkalmazások fejlesztésekor.

Miközben az adatobjektumokat oda-vissza mozgatjuk e rétegek között, gyakran tapasztalhatjuk, hogy az egyik példányból az egyikbe kell átalakítanunk az objektumokat a különböző API-k befogadására.

Néhány módszer ennek elérésére: keményen kódolva a másolási logikát, vagy olyan bab-leképezők megvalósításához, mint a Dozer. Használható azonban az egyik és a másik objektumréteg közötti leképezés folyamatának egyszerűsítésére.

Orika a bájtkód generálást használja a gyors leképezők létrehozásához minimális rezsivel, ami sokkal gyorsabb, mint a más tükröződésen alapuló térképezők, mint a Dozer.

2. Egyszerű példa

A leképezési keret alapköve a MapperFactory osztály. Ezt az osztályt fogjuk használni a leképezések konfigurálásához és a MapperFacade a tényleges feltérképezési munkát végző példány.

Létrehozunk egy MapperFactory objektum így:

MapperFactory mapperFactory = new DefaultMapperFactory.Builder (). Build ();

Akkor feltételezve, hogy van forrásadat-objektumunk, Forrás.java, két mezővel:

public class Forrás {private String name; privát int kor; nyilvános Forrás (karakterlánc neve, int kor) {ez.név = név; ez.kor = életkor; } // szokásos mérőeszközök és beállítók}

És egy hasonló rendeltetési objektum, Dest.java:

public class Dest {private String name; privát int kor; public Dest (karakterlánc neve, int kor) {this.név = név; ez.kor = életkor; } // szokásos mérőeszközök és beállítók}

Ez a legalapvetőbb a bab feltérképezése az Orika segítségével:

@Test public void givenSrcAndDest_whenMaps_thenCorrect () {mapperFactory.classMap (Source.class, Dest.class); MapperFacade mapper = mapperFactory.getMapperFacade (); Forrás src = új Forrás ("Baeldung", 10); Dest dest = mapper.map (src, Dest.class); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

Amint megfigyelhetjük, létrehoztuk a Rendeltetési hely objektum azonos mezőkkel, mint Forrás, egyszerűen feltérképezéssel. Alapértelmezés szerint kétirányú vagy fordított leképezés is lehetséges:

@Test public void givenSrcAndDest_whenMapsReverse_thenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .byDefault (); MapperFacade mapper = mapperFactory.getMapperFacade (); Dest src = új Dest ("Baeldung", 10); Forrás dest = mapper.map (src, Forrás.osztály); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

3. Maven Setup

Ahhoz, hogy Orika mappert használhassunk maven projektjeinkben, rendelkeznünk kell orika-mag függőség ben pom.xml:

 ma.glasnost.orika orika-core 1.4.6 

A legfrissebb verzió mindig itt található.

3. Munka MapperFactory

Az Orikával való leképezés általános mintája a MapperFactory objektumot, az incase konfigurálásához módosítanunk kell az alapértelmezett leképezési viselkedést, megszerezve a MapperFacade objektum és végül tényleges feltérképezés.

Ezt a mintát minden példánkban megfigyelni fogjuk. De a legelső példánk megmutatta a térképkészítő alapértelmezett viselkedését, anélkül, hogy a mi oldalunkon változtatnának.

3.1. A BoundMapperFacade vs. MapperFacade

Egy dolgot meg kell jegyezni, hogy választhattunk a használat mellett BoundMapperFacade az alapértelmezett felett MapperFacade ami meglehetősen lassú. Ezek olyan esetek, amikor egy meghatározott típusú párral kell feltérképeznünk.

Az első tesztünk így lesz:

@Test public void givenSrcAndDest_whenMapsUsingBoundMapper_thenCorrect () {BoundMapperFacade boundMapper = mapperFactory.getMapperFacade (Source.class, Dest.class); Forrás src = új Forrás ("baeldung", 10); Dest dest = kötöttMapper.map (src); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

Azonban azért BoundMapperFacade kétirányú feltérképezéshez kifejezetten hívnunk kell a mapReverse metódus helyett a térkép metódus, amelyet az alapértelmezett esetre kerestünk MapperFacade:

@Test public void givenSrcAndDest_whenMapsUsingBoundMapperInReverse_thenCorrect () {BoundMapperFacade boundMapper = mapperFactory.getMapperFacade (Source.class, Dest.class); Dest src = new Dest ("baeldung", 10); Forrás dest = kötöttMapper.mapReverse (src); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

A teszt egyébként sikertelen lesz.

3.2. Konfigurálja a mezőtérképeket

Az eddig megvizsgált példák azonos forrásnevű forrás- és célosztályokat tartalmaznak. Ez az alfejezet foglalkozik azzal az esettel, amikor különbség van a kettő között.

Tekintsünk egy forrásobjektumot, Személy , három mezővel, nevezetesen név, becenév és kor:

public class Személy {private String név; privát String becenév; privát int kor; public Person (karakterlánc neve, String beceneve, int kor) {this.név = név; ez.név = becenév; ez.kor = életkor; } // szokásos mérőeszközök és beállítók}

Ezután az alkalmazás egy másik rétegének van egy hasonló objektuma, de azt egy francia programozó írja. Tegyük fel, hogy hívják Personne, mezőkkel nom, surnom és kor, amelyek mindegyike megfelel a fenti háromnak:

nyilvános osztály Personne {privát húr nom; privát húrlánc; privát int kor; public Personne (String nom, String surnom, int age) {this.nom = nom; this.surnom = surnom; ez.kor = életkor; } // szokásos mérőeszközök és beállítók}

Orika nem tudja automatikusan megoldani ezeket a különbségeket. De használhatjuk a ClassMapBuilder API az egyedi leképezések regisztrálásához.

Korábban már használtuk, de még nem használtuk ki egyik erőteljes tulajdonságát sem. Az előző tesztek első sora az alapértelmezettet használva MapperFacade használta a ClassMapBuilder API az általunk feltérképezni kívánt két osztály regisztrálásához:

mapperFactory.classMap (Forrás.osztály, Célosztály);

Az összes mezőt feltérképezhetjük az alapértelmezett konfiguráció segítségével, hogy világosabb legyen:

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

A alapértelmezés szerint() metódus hívással, már konfiguráljuk a leképező viselkedését a ClassMapBuilder API.

Most szeretnénk feltérképezni Personne nak nek Személy, így a terepi leképezéseket a mapper segítségével is konfiguráljuk ClassMapBuilder API:

@Test public void givenSrcAndDestWithDifferentFieldNames_whenMaps_thenCorrect () {mapperFactory.classMap (Personne.class, Person.class) .field ("nom", "name"). Field ("surnom", "nickname") .field ("age", "" kor "). regisztráció (); MapperFacade mapper = mapperFactory.getMapperFacade (); Personne frenchPerson = new Personne ("Claire", "cla", 25); Személy englishPerson = mapper.map (franciaPerson, Person.class); assertEquals (angolPerson.getName (), frenchPerson.getNom ()); assertEquals (angolPerson.getNickname (), frenchPerson.getSurnom ()); assertEquals (angolPerson.getAge (), franciaPerson.getAge ()); }

Ne felejtsd el felhívni a Regisztráció() API módszer a konfiguráció regisztrálásához a MapperFactory.

Még ha csak egy mező is különbözik egymástól, ezen az úton haladva azt kell jelentenünk, hogy kifejezetten regisztrálnunk kell minden terepi leképezések, beleértve kor ami mindkét objektumban megegyezik, különben a nem regisztrált mezőt nem térképezik fel, és a teszt kudarcot vall.

Ez hamarosan unalmas lesz, mi van, ha csak egy mezőt akarunk feltérképezni a 20-ból, konfigurálnunk kell az összes leképezésüket?

Nem, nem akkor, amikor azt mondjuk a térképkészítőnek, hogy használja az alapértelmezett leképezési konfigurációt azokban az esetekben, amikor még nem határoztuk meg kifejezetten a leképezést:

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

Itt még nem definiáltuk a kor mezőben, de ennek ellenére a teszt sikeres lesz.

3.3. Mező kizárása

Feltéve, hogy ki akarjuk zárni a nom területe Personne a feltérképezésből - úgy, hogy a Személy Az objektum csak olyan mezőknél kap új értékeket, amelyek nincsenek kizárva:

@Test public void givenSrcAndDest_whenCanExcludeField_thenCorrect () {mapperFactory.classMap (Personne.class, Person.class) .exclude ("nom") .field ("surnom", "nickname") field ("age", "age"). Regisztráció(); MapperFacade mapper = mapperFactory.getMapperFacade (); Personne frenchPerson = new Personne ("Claire", "cla", 25); Személy englishPerson = mapper.map (franciaPerson, Person.class); assertEquals (null, angolPerson.getName ()); assertEquals (angolPerson.getNickname (), frenchPerson.getSurnom ()); assertEquals (angolPerson.getAge (), franciaPerson.getAge ()); }

Figyelje meg, hogyan zárjuk ki a MapperFactory és akkor vegye észre az első állítást is, ahol az értékét várjuk név ban,-ben Személy objektum maradni nulla, ennek eredményeként a térképezés során kizárták.

4. Gyűjtemények feltérképezése

Előfordulhat, hogy a célobjektum egyedi attribútumokkal rendelkezik, míg a forrásobjektum csak fenntartja a gyűjtemény minden tulajdonságát.

4.1. Listák és tömbök

Vegyünk egy forrásadat-objektumot, amelynek csak egy mezője van, a személyek nevének listája:

public class SzemélyNévLista {privát Lista névLista; public PersonNameList (List nameList) {this.névLista = névLista; }}

Most vegye figyelembe az elválasztott céladat-objektumunkat keresztnév és vezetéknév külön mezőkbe:

public class PersonNameParts {private String keresztnév; privát karakterlánc vezetéknév; public PersonNameParts (karakterlánc keresztnév, karakterlánc vezetéknév) {this.firstName = keresztnév; this.lastName = vezetékNév; }}

Tegyük fel, hogy nagyon biztosak vagyunk abban, hogy a 0 indexnél mindig ott lesz a keresztnév és az 1. indexnél mindig ott lesz vezetéknév.

Orika lehetővé teszi számunkra, hogy a zárójeles jelölést használjuk a gyűjtemény tagjainak eléréséhez:

@Test public void givenSrcWithListAndDestWithPrimitiveAttributes_whenMaps_thenCorrect () {mapperFactory.classMap (PersonNameList.class, PersonNameParts.class) .field ("nameList [0]", "firstName") .field ("nameList [1]. (); MapperFacade mapper = mapperFactory.getMapperFacade (); List nameList = Arrays.asList (új karakterlánc [] {"Sylvester", "Stallone"}); PersonNameList src = new PersonNameList (névLista); PersonNameParts dest = mapper.map (src, PersonNameParts.class); assertEquals (dest.getFirstName (), "Sylvester"); assertEquals (dest.getLastName (), "Stallone"); }

Még ha helyett is PersonNameList, nekünk volt PersonNameArray, ugyanaz a teszt megfelelne egy névtömbnek.

4.2. Térképek

Feltételezve, hogy forrásobjektumunknak van egy értéktérképe. Tudjuk, hogy van egy kulcs abban a térképben, első, amelynek értéke képviseli az embert keresztnév célobjektumunkban.

Hasonlóképpen tudjuk, hogy van még egy kulcs, utolsó, ugyanazon a térképen, amelynek értéke egy személyt képvisel vezetéknév a célobjektumban.

public class SzemélyNévTérkép {privát Térkép névtérkép; public PersonNameMap (Térkép névtérkép) {this.nameMap = névTérkép; }}

Az előző szakaszban szereplő esethez hasonlóan zárójeles jelölést használunk, de egy index átadása helyett átadjuk azt a kulcsot, amelynek értékét feltérképezni szeretnénk az adott célmezőbe.

Orika a kulcs lekérésének két módját fogadja el, mindkettőt a következő teszt képviseli:

@Test public void givenSrcWithMapAndDestWithPrimitiveAttributes_whenMaps_thenCorrect () {mapperFactory.classMap (PersonNameMap.class, PersonNameParts.class) .field ("nameMap ['first']", "firstName") .field ("nameMap [name] "vezetéknév") .register (); MapperFacade mapper = mapperFactory.getMapperFacade (); Map nameMap = új HashMap (); névMap.put ("első", "Leornado"); nameMap.put ("utolsó", "DiCaprio"); PersonNameMap src = new PersonNameMap (névtérkép); PersonNameParts dest = mapper.map (src, PersonNameParts.class); assertEquals (dest.getFirstName (), "Leornado"); assertEquals (dest.getLastName (), "DiCaprio"); }

Használhatunk egyetlen idézetet vagy kettős idézetet, de ez utóbbit meg kell kerülnünk.

5. Térkép beágyazott mezőket

Tegyük fel, hogy az előző gyűjteményes példák alapján a forrás adatobjektumunkon belül van egy másik adatátviteli objektum (DTO), amely a feltérképezni kívánt értékeket tárolja.

public class PersonContainer {privát név neve; public PersonContainer (Név neve) {this.name = név; }}
public class Név {private String keresztnév; privát karakterlánc vezetéknév; public Name (String keresztnév, String vezetéknév) {this.firstName = keresztnév; this.lastName = vezetékNév; }}

A beágyazott DTO tulajdonságainak eléréséhez és a célobjektumhoz való hozzárendeléséhez pontjelzést használunk, így:

@Test public void givenSrcWithNestedFields_whenMaps_thenCorrect () {mapperFactory.classMap (PersonContainer.class, PersonNameParts.class) .field ("name.firstName", "firstName") .field ("name.lastName", "lastName") register. ; MapperFacade mapper = mapperFactory.getMapperFacade (); PersonContainer src = new PersonContainer (új név ("Nick", "Canon")); PersonNameParts dest = mapper.map (src, PersonNameParts.class); assertEquals (dest.getFirstName (), "Nick"); assertEquals (dest.getLastName (), "Canon"); }

6. A nullértékek feltérképezése

Bizonyos esetekben érdemes ellenőrizni, hogy a nullákat feltérképezik vagy figyelmen kívül hagyják-e, amikor találkoznak velük. Alapértelmezés szerint az Orika null értékeket fog feltérképezni, ha találkoznak:

@Test public void givenSrcWithNullField_whenMapsThenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .byDefault (); MapperFacade mapper = mapperFactory.getMapperFacade (); Forrás src = új Forrás (null, 10); Dest dest = mapper.map (src, Dest.class); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

Ez a viselkedés különböző szinteken testreszabható attól függően, hogy milyen konkrétak szeretnénk lenni.

6.1. Globális konfiguráció

A térképkészítőt úgy konfigurálhatjuk, hogy a nullákat feltérképezze, vagy globális szinten figyelmen kívül hagyhassa őket, mielőtt létrehoznánk a globálist MapperFactory. Emlékszel, hogyan hoztuk létre ezt az objektumot az első példánkban? Ezúttal egy extra hívást adunk az összeállítási folyamat során:

MapperFactory mapperFactory = new DefaultMapperFactory.Builder () .mapNulls (false) .build ();

Futtathatunk egy tesztet annak megerősítésére, hogy a nullák valóban nem kerülnek feltérképezésre:

@Test public void givenSrcWithNullAndGlobalConfigForNoNull_whenFailsToMap_ThenCorrect () {mapperFactory.classMap (Source.class, Dest.class); MapperFacade mapper = mapperFactory.getMapperFacade (); Forrás src = új Forrás (null, 10); Dest dest = új Dest ("Clinton", 55); mapper.map (src, dest); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), "Clinton"); }

Az történik, hogy alapértelmezés szerint nullákat térképeznek fel. Ez azt jelenti, hogy még akkor is, ha a forrásobjektum mezőértéke az nulla és a célobjektum megfelelő mezőjének értéke van értelmes értékkel, felülírásra kerül.

Esetünkben a célmező nem íródik felül, ha a megfelelő forrásmezőnek van egy nulla érték.

6.2. Helyi konfiguráció

A térkép feltérképezése nulla értékek vezérelhetők a ClassMapBuilder a mapNulls (igaz | hamis) vagy mapNullsInReverse (true | false) a nullák fordított irányú leképezésének vezérléséhez.

Ha ezt az értéket a ClassMapBuilder például az összes ugyanazon a területen létrehozott leképezés ClassMapBuilder, az érték beállítása után ugyanazt az értéket veszi fel.

Illusztráljuk ezt egy példapéldával:

@Test public void givenSrcWithNullAndLocalConfigForNoNull_whenFailsToMap_ThenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .field ("age", "age") .mapNulls (false) .field ("név", "név"). ).Regisztráció(); MapperFacade mapper = mapperFactory.getMapperFacade (); Forrás src = új Forrás (null, 10); Dest dest = új Dest ("Clinton", 55); mapper.map (src, dest); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), "Clinton"); }

Figyeljük meg, hogyan hívjuk mapNulls közvetlenül regisztráció előtt név mezőt, ez az összes mezőt a mapNulls hívja figyelmen kívül hagyni, ha van nulla érték.

A kétirányú leképezés a leképezett null értékeket is elfogadja:

@Test public void givenDestWithNullReverseMappedToSource_whenMapsByDefault_thenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .byDefault (); MapperFacade mapper = mapperFactory.getMapperFacade (); Dest src = new Dest (null, 10); Forrás dest = új Forrás ("Vin", 44); mapper.map (src, dest); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), src.getName ()); }

Hívással megakadályozhatjuk ezt is mapNullsInReverse és bemegy hamis:

@Test public void givenDestWithNullReverseMappedToSourceAndLocalConfigForNoNull_whenFailsToMap_thenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .field ("age", "age") .mapNullsInReverse. ) .Regisztráció(); MapperFacade mapper = mapperFactory.getMapperFacade (); Dest src = new Dest (null, 10); Forrás dest = új Forrás ("Vin", 44); mapper.map (src, dest); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), "Vin"); }

6.3. Mezőszintű konfiguráció

Ezt terepi szinten konfigurálhatjuk a segítségével fieldMap, így:

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

Ebben az esetben a konfiguráció csak a név mező, ahogyan terepi szinten hívtuk:

@Test public void givenSrcWithNullAndFieldLevelConfigForNoNull_whenFailsToMap_ThenCorrect () {mapperFactory.classMap (Source.class, Dest.class) .field ("age", "age") .fieldMap ("name", "name"). ) .byDefault (). register (); MapperFacade mapper = mapperFactory.getMapperFacade (); Forrás src = új Forrás (null, 10); Dest dest = új Dest ("Clinton", 55); mapper.map (src, dest); assertEquals (dest.getAge (), src.getAge ()); assertEquals (dest.getName (), "Clinton"); }

7. Orika egyedi térképezés

Eddig egyszerű egyéni leképezési példákat vizsgáltunk a ClassMapBuilder API. Továbbra is ugyanazt az API-t fogjuk használni, de az Orika segítségével testreszabjuk a térképezésünket CustomMapper osztály.

Feltételezve, hogy két adatobjektumunk van, egyenként egy bizonyos mezővel dtob, amely egy személy születésének dátumát és idejét jelöli.

Egy adatobjektum ezt az értéket a-ként ábrázolja datetime karakterlánc a következő ISO formátumban:

2007-06-26T21: 22: 39Z

a másik pedig ugyanazt jelenti, mint az a hosszú írja be a következő unix időbélyegző formátumot:

1182882159000

Nyilvánvaló, hogy az általunk eddig lefedett testreszabások nem elegendőek a két formátum közötti átalakításhoz a leképezési folyamat során, még az Orika beépített átalakítója sem képes kezelni a feladatot. Itt kell megírnunk a CustomMapper hogy elvégezze a szükséges átalakítást a leképezés során.

Hozzuk létre az első adatobjektumunkat:

public class Személy3 {privát String név; privát húr dtob; public Person3 (karakterlánc neve, String dtob) {this.név = név; ez.dtob = dtob; }}

akkor a második adatobjektumunk:

public class Personne3 {privát karakterlánc neve; magán hosszú dtob; public Personne3 (karakterlánc neve, hosszú dtob) {this.név = név; ez.dtob = dtob; }}

Jelenleg nem jelöljük meg, hogy melyik a forrás és melyik a cél CustomMapper lehetővé teszi számunkra, hogy gondoskodjunk a kétirányú térképezésről.

Itt van a konkrét megvalósítás a CustomMapper absztrakt osztály:

class PersonCustomMapper kiterjeszti a CustomMapper alkalmazást {@Orride public void mapAtoB (Personne3 a, Person3 b, MappingContext context) {Date date = new Date (a.getDtob ()); DateFormat formátum = new SimpleDateFormat ("éééé-HH-nn.'H'HH: mm: ss'Z '"); Karakterlánc isoDate = format.format (dátum); b.setDtob (isoDate); } @Orride public void mapBtoA (Person3 b, Personne3 a, MappingContext context) {DateFormat format = new SimpleDateFormat ("yyyy-MM-dd'T'HH: mm: ss'Z '"); Dátum dátum = format.parse (b.getDtob ()); hosszú időbélyeg = date.getTime (); a.setDtob (időbélyeg); }};

Figyeljük meg, hogy módszereinket implementáltuk mapAtoB és mapBtoA. Mindkettő megvalósítása kétirányúvá teszi térképészeti funkciónkat.

Minden módszer kiteszi az általunk leképezett adatobjektumokat, és mi gondoskodunk a mezőértékek egyikről a másikra történő másolásáról.

Itt írjuk az egyéni kódot, hogy a forrásadatokat az igényeink szerint kezeljük, mielőtt a célobjektumba írnánk.

Futtassunk egy tesztet annak igazolására, hogy az egyedi térképkészítőnk működik:

@Test public void givenSrcAndDest_whenCustomMapperWorks_thenCorrect () {mapperFactory.classMap (Personne3.class, Person3.class) .customize (customMapper) .register (); MapperFacade mapper = mapperFactory.getMapperFacade (); String dateTime = "2007-06-26T21: 22: 39Z"; hosszú időbélyeg = új Hosszú ("1182882159000"); Personne3 personne3 = new Personne3 ("Leornardo", időbélyeg); Person3 person3 = mapper.map (personne3, Person3.osztály); assertEquals (person3.getDtob (), dateTime); }

Figyelje meg, hogy az egyedi leképezőt továbbra is továbbítjuk Orika térképezőjének ClassMapBuilder API, csakúgy, mint az összes többi egyszerű testreszabás.

Azt is megerősíthetjük, hogy a kétirányú térképezés működik:

@Test public void givenSrcAndDest_whenCustomMapperWorksBidirectionally_thenCorrect () {mapperFactory.classMap (Personne3.class, Person3.class) .customize (customMapper) .register (); MapperFacade mapper = mapperFactory.getMapperFacade (); String dateTime = "2007-06-26T21: 22: 39Z"; hosszú időbélyeg = új Hosszú ("1182882159000"); Person3 person3 = new Person3 ("Leornardo", dateTime); Personne3 personne3 = mapper.map (person3, Personne3.osztály); assertEquals (person3.getDtob (), időbélyeg); }

8. Következtetés

Ebben a cikkben van feltárta az Orika térképészeti keret legfontosabb jellemzőit.

Mindenképpen vannak olyan fejlettebb funkciók, amelyek sokkal jobb irányítást biztosítanak számunkra, de a legtöbb használati esetben az itt bemutatottak több mint elegendőek lesznek.

A teljes projekt kód és az összes példa megtalálható a github projektemben. Ne felejtse el megnézni a Dozer leképezési keretrendszerről szóló bemutatónkat is, mivel mindkettő nagyjából ugyanazt a problémát oldja meg.