Kartlegge samlinger med MapStruct

1. Oversikt

I denne opplæringen tar vi en titt på hvordan man kartlegger samlinger av objekter ved hjelp av MapStruct.

Siden denne artikkelen allerede forutsetter en grunnleggende forståelse av MapStruct, bør nybegynnere sjekke ut vår hurtigguide til MapStruct først.

2. Kartleggingssamlinger

Generelt, kartlegging av samlinger med MapStruct fungerer på samme måte som for enkle typer.

I utgangspunktet må vi lage et enkelt grensesnitt eller en abstrakt klasse og erklære kartleggingsmetodene. Basert på våre erklæringer vil MapStruct generere kartleggingskoden automatisk. Typisk, den genererte koden vil løpe over kildesamlingen, konvertere hvert element til måltypen og inkludere hver av dem i målsamlingen.

La oss ta en titt på et enkelt eksempel.

2.1. Kartlister

Først, for vårt eksempel, la oss vurdere en enkel POJO som kartleggingskilde for kartleggeren vår:

offentlig klasse Ansatt {privat streng fornavn; privat streng etternavn; // constructor, getters and setters} 

Målet vil være en enkel DTO:

offentlig klasse EmployeeDTO {private String firstName; privat streng etternavn; // getters og setters}

Deretter la oss definere kartleggeren vår:

@Mapper offentlig grensesnitt EmployeeMapper {Liste kart (Liste ansatte); } 

Til slutt, la oss se på koden MapStruct generert fra vår EmployeeMapper grensesnitt:

offentlig klasse EmployeeMapperImpl implementerer EmployeeMapper {@Override public List map (Liste ansatte) {if (ansatte == null) {return null; } Liste liste = ny ArrayList (ansatte.størrelse ()); for (Ansatt ansatt: ansatte) {list.add (ansatteToEmployeeDTO (ansatt)); } returliste; } beskyttet EmployeeDTO-medarbeiderToEmployeeDTO (ansatt ansatt) {if (medarbeider == null) {return null; } EmployeeDTO-medarbeiderDTO = ny EmployeeDTO (); ansatteDTO.setFirstName (ansatt.getFirstnavn ()); medarbeiderDTO.setLastnavn (ansatt.getLastnavn ()); retur ansattDTO; }} 

Det er en viktig ting å merke seg. Nærmere bestemt, MapStruct generert for oss automatisk kartleggingen fra Ansatt til EmployeeDTO.

Det er tilfeller når dette ikke er mulig. La oss for eksempel si at vi vil kartlegge våre Ansatt modell til følgende modell:

offentlig klasse EmployeeFullNameDTO {private String fullName; // getter og setter}

I dette tilfellet, hvis vi bare erklærer kartleggingsmetoden fra en Liste av Ansatt til en Liste av EmployeeFullNameDTO vi mottar en kompilasjonsfeil eller advarsel som:

Advarsel: (11, 31) java: Ikke-kartlagt målegenskap: "fullName". Kartlegging fra innsamlingselementet "com.baeldung.mapstruct.mappingCollections.model.Employee employee" til "com.baeldung.mapstruct.mappingCollections.dto.EmployeeFullNameDTO employeeFullNameDTO".

I utgangspunktet betyr dette det MapStruct kunne ikke generere kartleggingen automatisk for ossi dette tilfellet. Derfor må vi definere kartleggingen manuelt Ansatt og EmployeeFullNameDTO.

Gitt disse poengene, la oss definere det manuelt:

@Mapper offentlig grensesnitt EmployeeFullNameMapper {Liste kart (Liste ansatte); standard EmployeeFullNameDTO-kart (ansatt ansatt) {EmployeeFullNameDTO medarbeiderInfoDTO = ny EmployeeFullNameDTO (); ansattInfoDTO.setFullName (ansatt.getFirstnavn () + "" + ansatt.getLastnavn ()); retur ansattInfoDTO; }}

Den genererte koden vil bruke metoden vi definerte for å kartlegge elementene i kilden Liste til målet Liste.

Dette gjelder også generelt. Hvis vi har definert en metode som tilordner kildeelementtypen til målelementtypen, vil MapStruct bruke den.

2.2. Kartleggingssett og kart

Kartleggingssett med MapStruct fungerer på samme måte som med lister. La oss for eksempel si at vi vil kartlegge a Sett av Ansatt forekomster til en Sett av EmployeeDTO tilfeller.

Som før trenger vi en kartlegger:

@Mapper offentlig grensesnitt EmployeeMapper {Sett kart (Sett ansatte); }

Og MapStruct vil generere riktig kode:

offentlig klasse EmployeeMapperImpl implementerer EmployeeMapper {@Override public Sett kart (Sett ansatte) {if (ansatte == null) {return null; } Sett sett = nytt HashSet (Math.max ((int) (ansatte.størrelse () / .75f) + 1, 16)); for (Ansatt ansatt: ansatte) {set.add (ansatteToEmployeeDTO (ansatt)); } retur sett; } beskyttet EmployeeDTO-medarbeiderToEmployeeDTO (ansatt ansatt) {if (medarbeider == null) {return null; } EmployeeDTO-medarbeiderDTO = ny EmployeeDTO (); ansatteDTO.setFirstName (medarbeider.getFirstName ()); medarbeiderDTO.setLastnavn (ansatt.getLastnavn ()); retur ansattDTO; }}

Det samme gjelder kart. La oss vurdere at vi vil kartlegge a Kart til en Kart.

Deretter kan vi følge de samme trinnene som før:

@Mapper offentlig grensesnitt EmployeeMapper {Map map (Map idEmployeeMap); }

Og MapStruct gjør jobben sin:

offentlig klasse EmployeeMapperImpl implementerer EmployeeMapper {@Override public Map map (Map idEmployeeMap) {if (idEmployeeMap == null) {return null; } Kartkart = nytt HashMap (Math.max ((int) (idEmployeeMap.size () / .75f) + 1, 16)); for (java.util.Map.Entry entry: idEmployeeMap.entrySet ()) {String key = entry.getKey (); EmployeeDTO-verdi = workerToEmployeeDTO (entry.getValue ()); map.put (nøkkel, verdi); } retur kart; } beskyttet EmployeeDTO-medarbeiderToEmployeeDTO (ansatt ansatt) {if (medarbeider == null) {return null; } EmployeeDTO-medarbeiderDTO = ny EmployeeDTO (); ansatteDTO.setFirstName (medarbeider.getFirstName ()); medarbeiderDTO.setLastnavn (ansatt.getLastnavn ()); retur ansattDTO; }}

3. Kartleggingsstrategier for samlinger

Ofte må vi kartlegge datatyper som har et foreldre-barn forhold. Vanligvis har vi en datatype (foreldre) som har felt a Samling av en annen datatype (barn).

For slike tilfeller, MapStruct tilbyr en måte å velge hvordan du skal sette eller legge barna til foreldretypen. Spesielt den @Kartlegger merknader har en collectionMappingStrategy attributt som kan være ACCESSOR_ONLY, SETTER_ FORETRUKT, ADDER_ FORETRUKT eller TARGET_IMMUTABLE.

Alle disse verdiene refererer til måten barna skal settes på eller legges til foreldretypen. Standardverdien er ACCESSOR_ONLY, som betyr at bare tilbehør kan brukes til å stille inn Samling av barn.

Dette alternativet er nyttig når setter for Samling feltet er ikke tilgjengelig, men vi har en adder. Et annet tilfelle der dette er nyttig er når Samling er uforanderlig på foreldretypen. Vanligvis støter vi på disse sakene i genererte måltyper.

3.1. ACCESSOR_ONLY Collection Mapping Strategy

La oss ta et eksempel for bedre å forstå hvordan dette fungerer.

For vårt eksempel, la oss lage en Selskap klasse som vår kartleggingskilde:

offentlig klasse Company {private List ansatte; // getter og setter}

Og målet for kartleggingen vår vil være en enkel DTO:

offentlig klasse CompanyDTO {private List ansatte; offentlig Liste getEmployees () {return ansatte; } public void setMedarbeidere (liste ansatte) {dette.medarbeidere = ansatte; } offentlig ugyldig addEmployee (EmployeeDTO-medarbeiderDTO) {if (ansatte == null) {ansatte = ny ArrayList (); } ansatte.add (medarbeiderDTO); }}

Merk at vi har begge setterne, settMedarbeidere, og huggeren, legg til Ansatt, tilgjengelig. Også, for huggeren er vi ansvarlige for initialisering av samlingen.

La oss si at vi vil kartlegge en Selskap til en CompanyDTO. Så som før trenger vi en kartlegger:

@Mapper (bruker = EmployeeMapper.class) offentlig grensesnitt CompanyMapper {CompanyDTO-kart (selskapsselskap); }

Merk at vi brukte EmployeeMapper og standard collectionMappingStrategy.

La oss nå ta en titt på koden MapStruct generert:

offentlig klasse CompanyMapperImpl implementerer CompanyMapper {private final EmployeeMapper employeeMapper = Mappers.getMapper (EmployeeMapper.class); @Override public CompanyDTO map (Company company) {if (company == null) {return null; } CompanyDTO companyDTO = ny CompanyDTO (); companyDTO.setEmployees (ansatteMapper.map (company.getEmployees ())); retur selskapDTO; }}

Som man kan se, MapStruct bruker setteren, settMedarbeidere, for å stille inn Liste av EmployeeDTO tilfeller. Dette skjer fordi her bruker vi standard collectionMappingStrategy,ACCESSOR_ONLY.

MapStruct fant også en metodekartlegging a Liste til en Liste i EmployeeMapper og brukte den på nytt.

3.2. ADDER_ FORETRUKT Collection Mapping Strategy

La oss derimot vurdere at vi brukte ADDER_ FORETRUKT som collectionMappingStrategy:

@Mapper (collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, bruker = EmployeeMapper.class) offentlig grensesnitt CompanyMapperAdderPreferred {CompanyDTO-kart (selskapsselskap); }

Igjen, vi ønsker å gjenbruke EmployeeMapper. Derimot, vi må eksplisitt legge til en metode som kan konvertere en enkelt Ansatt til en EmployeeDTO først:

@Mapper offentlig grensesnitt EmployeeMapper {EmployeeDTO-kart (ansatt ansatt); Liste kart (Liste ansatte); Sett kart (Sett ansatte); Kartkart (Map idEmployeeMap); }

Dette er fordi MapStruct vil bruke adderen til å legge til EmployeeDTO forekomster til målet CompanyDTO eksempel en etter en:

offentlig klasse CompanyMapperAdderPreferredImpl implementerer CompanyMapperAdderPreferred {private final EmployeeMapper medarbeiderMapper = Mappers.getMapper (EmployeeMapper.class); @Override public CompanyDTO map (Company company) {if (company == null) {return null; } CompanyDTO companyDTO = ny CompanyDTO (); hvis (company.getEmployees ()! = null) {for (ansatt ansatt: company.getEmployees ()) {companyDTO.addEmployee (ansatteMapper.map (ansatt)); }} returnere selskapDTO; }}

I tilfelle huggeren ikke var tilgjengelig, ville setteren blitt brukt.

Vi finner en fullstendig beskrivelse av alle strategiene for kartlegging av samlinger i MapStruct's referansedokumentasjon.

4. Implementeringstyper for målsamling

MapStruct støtter samlingsgrensesnitt som måltyper til kartleggingsmetoder.

I dette tilfellet brukes noen standardimplementeringer i den genererte koden. For eksempel standardimplementeringen for Liste er ArrayList som det kan bemerkes fra eksemplene våre ovenfor.

Vi finner den komplette listen over grensesnitt som MapStruct støtter, og standardimplementeringene den bruker for hvert grensesnitt, i referansedokumentasjonen.

5. Konklusjon

I denne artikkelen har vi undersøkt hvordan du kartlegger samlinger ved hjelp av MapStruct.

Først har vi sett på hvordan vi kan kartlegge forskjellige typer samlinger. Så så vi hvordan vi kan tilpasse kartleggere for foreldre-forhold relasjoner ved hjelp av strategier for kartlegging av samlinger.

Underveis markerte vi nøkkelpunktene og tingene du må huske på mens vi kartlegger samlinger ved hjelp av MapStruct.

Som vanlig er den komplette koden tilgjengelig på GitHub.


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