Utførelse av Java Mapping Frameworks

1. Introduksjon

Å lage store Java-applikasjoner sammensatt av flere lag krever bruk av flere modeller, slik som utholdenhetsmodell, domenemodell eller såkalte DTO-er. Å bruke flere modeller for forskjellige applikasjonslag vil kreve at vi gir en måte å kartlegge mellom bønner.

Å gjøre dette manuelt kan raskt opprette mye kjelekode og forbruke mye tid. Heldigvis for oss er det flere rammer for kartlegging av objekter for Java.

I denne opplæringen skal vi sammenligne ytelsen til de mest populære rammene for Java-kartlegging.

2. Kartleggingsrammer

2.1. Bulldoser

Dozer er et kartleggingsrammeverk som bruker rekursjon til å kopiere data fra ett objekt til et annet. Rammeverket kan ikke bare kopiere egenskaper mellom bønnene, men det kan også konverteres automatisk mellom forskjellige typer.

For å bruke Dozer-rammeverket må vi legge til en slik avhengighet i prosjektet vårt:

 com.github.dozermapper dozer-core 6.5.0 

Mer informasjon om bruken av Dozer-rammeverket finner du i denne artikkelen.

Dokumentasjonen av rammeverket finner du her.

2.2. Orika

Orika er et rammeverk for kartlegging av bønner til bønner som rekursivt kopierer data fra ett objekt til et annet.

Det generelle prinsippet om arbeidet til Orika ligner Dozer. Hovedforskjellen mellom de to er det faktum at Orika bruker generering av bykode. Dette gir mulighet for å generere raskere kartleggere med minimal overhead.

For å bruke den,vi må legge til slik avhengighet i prosjektet vårt:

 ma.glasnost.orika orika-core 1.5.4 

Mer detaljert informasjon om bruken av Orika finner du i denne artikkelen.

Den faktiske dokumentasjonen av rammeverket finner du her.

2.3. MapStruct

MapStruct er en kodegenerator som genererer klasser for bønnekartleggere automatisk.

MapStruct har også muligheten til å konvertere mellom forskjellige datatyper. Mer informasjon om hvordan du bruker den finner du i denne artikkelen.

For å legge til MapStructtil prosjektet vårt må vi inkludere følgende avhengighet:

 org.mapstruct mapstruct 1.3.1.Final 

Dokumentasjonen av rammeverket finner du her.

2.4. ModelMapper

ModelMapper er et rammeverk som tar sikte på å forenkle objektkartlegging, ved å bestemme hvordan objekter kartlegges til hverandre basert på konvensjoner. Det gir typesikker og refactoring-safe API.

Mer informasjon om rammeverket finner du i dokumentasjonen.

For å inkludere ModelMapper i prosjektet vårt, må vi legge til følgende avhengighet:

 org.modelmapper modelmapper 2.3.8 

2.5. JMapper

JMapper er kartleggingsrammeverket som tar sikte på å gi en brukervennlig, høy ytelse kartlegging mellom Java Beans.

Rammeverket har som mål å anvende DRY-prinsippet ved hjelp av merknader og relasjonskartlegging.

Rammeverket tillater forskjellige måter å konfigurere på: kommentarbasert, XML- eller API-basert.

Mer informasjon om rammeverket finner du i dokumentasjonen.

For å inkludere JMapper i prosjektet vårt, må vi legge til avhengighet:

 com.googlecode.jmapper-framework jmapper-core 1.6.1.CR2 

3. TestingModell

For å kunne teste kartlegging riktig må vi ha kilde- og målmodeller. Vi har laget to testmodeller.

Den første er bare en enkel POJO med en String felt tillot dette oss å sammenligne rammer i enklere tilfeller og sjekke om noe endres hvis vi bruker mer kompliserte bønner.

Den enkle kildemodellen ser ut som nedenfor:

offentlig klasse SourceCode {Strengkode; // getter og setter}

Og destinasjonen er ganske lik:

offentlig klasse Destinasjonskode {Strengkode; // getter og setter}

Det virkelige eksemplet på kilde bønner ser slik ut:

offentlig klasse SourceOrder {private String orderFinishDate; privat PaymentType betalingType; privat rabattrabatt; private DeliveryData leveringData; privat brukerbestilling Bruker; privat liste bestilt Produkter; privat butikk tilbudShop; privat int orderId; privat OrderStatus-status; privat LocalDate orderDate; // standard getters og setters}

Og målklassen ser ut som nedenfor:

public class Order {private User orderingUser; privat liste bestilt Produkter; privat OrderStatus orderStatus; privat LocalDate orderDate; privat LocalDate orderFinishDate; privat PaymentType betalingType; privat rabattrabatt; privat int shopId; private DeliveryData leveringData; privat butikk tilbudShop; // standard getters og setters}

Hele modellstrukturen finner du her.

4. Omformere

For å forenkle utformingen av testoppsettet har vi laget Konverter grensesnitt:

offentlig grensesnittkonverterer {Order convert (SourceOrder sourceOrder); DestinationCode konvertere (SourceCode sourceCode); }

Og alle våre tilpassede kartleggere vil implementere dette grensesnittet.

4.1. OrikaConverter

Orika tillater full API-implementering, dette forenkler i stor grad opprettelsen av kartleggeren:

offentlig klasse OrikaConverter implementerer Converter {private MapperFacade mapperFacade; offentlig OrikaConverter () {MapperFactory mapperFactory = ny DefaultMapperFactory .Builder (). build (); mapperFactory.classMap (Order.class, SourceOrder.class) .field ("orderStatus", "status"). byDefault (). register (); mapperFacade = mapperFactory.getMapperFacade (); } @ Override public Order convert (SourceOrder sourceOrder) {return mapperFacade.map (sourceOrder, Order.class); } @Override public DestinationCode convert (SourceCode sourceCode) {return mapperFacade.map (sourceCode, DestinationCode.class); }}

4.2. DozerConverter

Dozer krever XML-mappefil, med følgende seksjoner:

  com.baeldung.performancetests.model.source.SourceOrder com.baeldung.performancetests.model.destination.Order status ordre status    com.baeldung.performancetests.model.source.SourceCode com.baeldung.performancetests.model.destination.DestinationCode 

Etter å ha definert XML-kartleggingen, kan vi bruke den fra kode:

offentlig klasse DozerConverter implementerer Converter {private final Mapper mapper; offentlig DozerConverter () {this.mapper = DozerBeanMapperBuilder.create () .withMappingFiles ("dozer-mapping.xml") .build (); } @ Override public Order convert (SourceOrder sourceOrder) {return mapper.map (sourceOrder, Order.class); } @Override public DestinationCode convert (SourceCode sourceCode) {return mapper.map (sourceCode, DestinationCode.class); }}

4.3. MapStructConverter

MapStruct-definisjonen er ganske enkel, da den er helt basert på kodegenerering:

@Mapper offentlig grensesnitt MapStructConverter utvider Converter {MapStructConverter MAPPER = Mappers.getMapper (MapStructConverter.class); @Mapping (source = "status", target = "orderStatus") @ Override Order convert (SourceOrder sourceOrder); @Override DestinationCode konvertere (SourceCode sourceCode); }

4.4. JMapperConverter

JMapperConverter krever mer arbeid å gjøre. Etter implementering av grensesnittet:

offentlig klasse JMapperConverter implementerer Converter {JMapper realLifeMapper; JMapper simpleMapper; public JMapperConverter () {JMapperAPI api = new JMapperAPI () .add (JMapperAPI.mappedClass (Order.class)); realLifeMapper = ny JMapper (Order.class, SourceOrder.class, api); JMapperAPI simpleApi = ny JMapperAPI () .add (JMapperAPI.mappedClass (DestinationCode.class)); simpleMapper = ny JMapper (DestinationCode.class, SourceCode.class, simpleApi); } @Override public Order convert (SourceOrder sourceOrder) {return (Order) realLifeMapper.getDestination (sourceOrder); } @Override public DestinationCode convert (SourceCode sourceCode) {return (DestinationCode) simpleMapper.getDestination (sourceCode); }}

Vi må også legge til @JMap merknader til hvert felt i målklassen. Dessuten kan JMapper ikke konvertere mellom enumtyper alene, og det krever at vi oppretter egendefinerte kartleggingsfunksjoner:

@JMapConversion (fra = "betalingstype", til = "betalingstype") offentlig betalingstypekonvertering (com.baeldung.performancetests.model.source.PaymentType type) {PaymentType betalingstype = null; switch (type) {case CARD: paymentType = PaymentType.CARD; gå i stykker; sak CASH: paymentType = PaymentType.CASH; gå i stykker; sak TRANSFER: paymentType = PaymentType.TRANSFER; gå i stykker; } return betalingType; }

4.5. ModelMapperConverter

ModelMapperConverter krever at vi bare oppgir klassene vi vil kartlegge:

offentlig klasse ModelMapperConverter implementerer Converter {private ModelMapper modelMapper; offentlig ModelMapperConverter () {modelMapper = ny ModelMapper (); } @Override public Order convert (SourceOrder sourceOrder) {return modelMapper.map (sourceOrder, Order.class); } @Override public DestinationCode convert (SourceCode sourceCode) {return modelMapper.map (sourceCode, DestinationCode.class); }}

5. Enkel modelltesting

For ytelsestesting kan vi bruke Java Microbenchmark Harness, mer informasjon om hvordan du bruker den finner du i denne artikkelen.

Vi har laget en egen referanseindeks for hver Konverter med å spesifisere BenchmarkMode til Mode. Alle.

5.1. Gjennomsnittstid

JMH returnerte følgende resultater for gjennomsnittlig kjøretid (jo mindre jo bedre):

RammeverkGjennomsnittlig kjøretid (i ms per operasjon)
MapStruct10 -5
JMapper10 -5
Orika0.001
ModelMapper0.001
Bulldoser0.002

Denne referansen viser tydelig at både MapStruct og JMapper har de beste gjennomsnittlige arbeidstidene.

5.2. Gjennomstrømning

I denne modusen returnerer referanseverdien antall operasjoner per sekund. Vi har mottatt følgende resultater (mer er bedre) :

RammeverkGjennomstrømning (i operasjoner per ms)
MapStruct133719
JMapper106978
Orika1800
ModelMapper978
Bulldoser471

I gjennomstrømningsmodus var MapStruct den raskeste av de testede rammene, med JMapper et nært sekund.

5.3. SingleShotTime

Denne modusen gjør det mulig å måle tiden for enkeltoperasjon fra begynnelsen til slutten. Referansen ga følgende resultat (mindre er bedre):

RammeverkSingle Shot Time (i ms per operasjon)
JMapper0.015
MapStruct0.450
Bulldoser2.094
Orika2.898
ModelMapper4.837

Her ser vi at JMapper gir bedre resultater enn MapStruct.

5.4. SampleTime

Denne modusen tillater prøvetaking av tiden for hver operasjon. Resultatene for tre forskjellige persentiler ser ut som nedenfor:

Eksempeltid (i millisekunder per operasjon)
Rammeverkp0,90s0.999p1.0
JMapper10-40.0012.6
MapStruct10-40.0013
Orika0.0010.0104
ModelMapper0.0020.0153.2
Bulldoser0.0030.02125

Alle referanser har vist at MapStruct og JMapper begge er gode valg, avhengig av scenariet.

6. Testing av virkelige modeller

For ytelsestesting kan vi bruke Java Microbenchmark Harness, mer informasjon om hvordan du bruker den finner du i denne artikkelen.

Vi har laget en egen referanseindeks for hver Konverter med å spesifisere BenchmarkMode til Mode. Alle.

6.1. Gjennomsnittstid

JMH returnerte følgende resultater for gjennomsnittlig kjøretid (mindre er bedre):

RammeverkGjennomsnittlig kjøretid (i ms per operasjon)
MapStruct10 -4
JMapper10 -4
Orika0.004
ModelMapper0.059
Bulldoser0.103

6.2. Gjennomstrømning

I denne modusen returnerer referanseverdien antall operasjoner per sekund. For hver kartlegger har vi mottatt følgende resultater (mer er bedre):

RammeverkGjennomstrømning (i operasjoner per ms)
JMapper7691
MapStruct7120
Orika281
ModelMapper19
Bulldoser10

6.3. SingleShotTime

Denne modusen gjør det mulig å måle tiden for enkel operasjon fra begynnelsen til slutten. Referansen ga følgende resultater (mindre er bedre):

RammeverkSingle Shot Time (i ms per operasjon)
JMapper0.253
MapStruct0.532
Bulldoser9.495
ModelMapper16.288
Orika18.081

6.4. SampleTime

Denne modusen tillater prøvetaking av tiden for hver operasjon. Samplingsresultatene er delt inn i prosentiler, vi presenterer resultater for tre forskjellige prosentiler p0,90, p0,999, og p1.00:

Eksempeltid (i millisekunder per operasjon)
Rammeverkp0,90s0.999p1.0
JMapper10-30.00864
MapStruct10-30.01068
Orika0.0060.27832
ModelMapper0.0832.39897
Bulldoser0.1464.526118

Mens de eksakte resultatene av det enkle eksemplet og det virkelige eksemplet var helt forskjellige, men de følger mer eller mindre den samme trenden. I begge eksemplene så vi en tett konkurranse mellom JMapper og MapStruct om topplasseringen.

6.5. Konklusjon

Basert på den virkelige modelltesten vi utførte i denne delen, kan vi se at den beste ytelsen helt klart tilhører JMapper, selv om MapStruct er et nært sekund. I de samme testene ser vi at Dozer er konsekvent nederst i resultattabellen vår, bortsett fra SingleShotTime.

7. Sammendrag

I denne artikkelen har vi gjennomført ytelsestester av fem populære Java bønne kartleggingsrammer: ModelMapper, MapStruct, Orika, Dozer og JMapper.

Som alltid kan kodeeksempler bli funnet på GitHub.


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