Izvedba Java Mapping Frameworks

1. Uvod

Stvaranje velikih Java aplikacija sastavljenih od više slojeva zahtijeva upotrebu više modela poput modela trajnosti, modela domene ili takozvanih DTO-a. Korištenje više modela za različite slojeve aplikacije tražit će od nas da pružimo način mapiranja između graha.

Ako to učinite ručno, možete brzo stvoriti mnogo uzorka i potrošiti puno vremena. Srećom po nas, postoji više okvira za mapiranje objekata za Javu.

U ovom uputstvu usporedit ćemo izvedbu najpopularnijih okvira za mapiranje Java.

2. Okviri za mapiranje

2.1. Buldožer

Dozer je okvir za mapiranje koji koristi rekurziju za kopiranje podataka s jednog objekta na drugi. Okvir je sposoban ne samo kopirati svojstva između graha, već također može automatski pretvoriti između različitih vrsta.

Da bismo koristili Dozer framework, moramo našem projektu dodati takvu ovisnost:

 com.github.dozermapper dozer-core 6.5.0 

Više informacija o upotrebi okvira Dozer možete pronaći u ovom članku.

Dokumentaciju okvira možete pronaći ovdje.

2.2. Orika

Orika je okvir za mapiranje graha u grah koji rekurzivno kopira podatke s jednog objekta na drugi.

Općenito načelo rada Orike slično je Dozeru. Glavna razlika između njih dvojice je činjenica da Orika koristi generiranje bytecode-a. To omogućuje stvaranje bržih karata s minimalnim troškovima.

Da biste ga koristili,trebamo dodati takvu ovisnost našem projektu:

 ma.glasnost.orika orika-core 1.5.4 

Detaljnije informacije o korištenju Orike možete pronaći u ovom članku.

Stvarnu dokumentaciju okvira možete pronaći ovdje.

2.3. MapStruct

MapStruct je generator koda koji automatski generira klase mapiranja graha.

MapStruct također ima mogućnost pretvorbe između različitih vrsta podataka. Više informacija o tome kako ga koristiti možete pronaći u ovom članku.

Da biste dodali MapStructu naš projekt moramo uključiti sljedeću ovisnost:

 org.mapstruct mapstruct 1.3.1.Final 

Dokumentaciju okvira možete pronaći ovdje.

2.4. ModelMapper

ModelMapper je okvir čiji je cilj pojednostaviti mapiranje objekata, određivanjem kako se objekti međusobno mapiraju na temelju konvencija. Pruža API siguran za tipove i refaktoriranje.

Više informacija o okviru možete pronaći u dokumentaciji.

Da bismo uključili ModelMapper u naš projekt, moramo dodati sljedeću ovisnost:

 org.modelmapper modelmapper 2.3.8 

2.5. JMapper

JMapper je okvir za mapiranje koji ima za cilj pružiti jednostavno mapiranje visokih performansi između Java Beans-a.

Okvir ima za cilj primjenu principa SUHOG koristeći bilješke i relacijsko mapiranje.

Okvir omogućuje različite načine konfiguracije: na temelju bilješki, XML ili API.

Više informacija o okviru može se naći u njegovoj dokumentaciji.

Da bismo uključili JMapper u naš projekt, moramo dodati njegovu ovisnost:

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

3. IspitivanjeModel

Da bismo mogli pravilno testirati mapiranje, moramo imati izvorni i ciljni model. Stvorili smo dva modela testiranja.

Prvo je samo jednostavan POJO s jednim Niz polje, to nam je omogućilo usporedbu okvira u jednostavnijim slučajevima i provjeru mijenja li se što ako koristimo složeniji grah.

Jednostavni izvorni model izgleda dolje:

javna klasa SourceCode {String kod; // dobivač i postavljač}

A odredište je prilično slično:

javna klasa DestinationCode {String code; // dobivač i postavljač}

Primjer izvornog graha u stvarnom životu izgleda ovako:

javna klasa SourceOrder {private String orderFinishDate; privateTip plaćanjaTip plaćanja; privatni popust s popustom; privatni DeliveryData deliveryData; privatni korisnik koji naručuje korisnika; privatni popis naručeniProizvodi; privatna trgovina nudiShop; private int orderId; status privatnog OrderStatusa; privatni LocalDate orderDate; // standardni geteri i postavljači}

A ciljna klasa izgleda dolje:

narudžba javne klase {private user orderingUser; privatni popis naručeniProizvodi; privatni OrderStatus orderStatus; privatni LocalDate orderDate; privatni LocalDate orderFinishDate; private PaymentType vrsta plaćanja; privatni popust s popustom; privatni int shopId; privatni DeliveryData deliveryData; privatna trgovina nudiShop; // standardni geteri i postavljači}

Cijelu strukturu modela možete pronaći ovdje.

4. Pretvarači

Da bismo pojednostavili dizajn postavki testiranja, stvorili smo Konverter sučelje:

pretvarač javnog sučelja {Pretvori narudžbu (SourceOrder sourceOrder); Pretvorba odredišnog koda (SourceCode sourceCode); }

I svi naši prilagođeni maperi implementirat će ovo sučelje.

4.1. OrikaConverter

Orika omogućuje potpunu implementaciju API-ja, što uvelike pojednostavljuje izradu mappera:

javna klasa OrikaConverter implementira Converter {private MapperFacade mapperFacade; javno OrikaConverter () {MapperFactory mapperFactory = novo DefaultMapperFactory .Builder (). build (); mapperFactory.classMap (Order.class, SourceOrder.class) .field ("orderStatus", "status"). byDefault (). register (); mapperFacade = mapperFactory.getMapperFacade (); } @Override pretvorba javne narudžbe (SourceOrder sourceOrder) {return mapperFacade.map (sourceOrder, Order.class); } @Override public DestinationCode convert (SourceCode sourceCode) {return mapperFacade.map (sourceCode, DestinationCode.class); }}

4.2. DozerConverter

Dozer zahtijeva XML datoteku za mapiranje sa sljedećim odjeljcima:

  com.baeldung.performancetests.model.source.SourceOrder com.baeldung.performancetests.model.destination. Status narudžbe stanje narudžbe    com.baeldung.performancetests.model.source.SourceCode com.baeldung.performancetests.model.destination.DestinationCode 

Nakon definiranja XML mapiranja, možemo ga koristiti iz koda:

javna klasa DozerConverter implementira Converter {privatni konačni Mapper mapper; javni DozerConverter () {this.mapper = DozerBeanMapperBuilder.create () .withMappingFiles ("dozer-mapping.xml") .build (); } @Override javni nalog za pretvorbu (SourceOrder sourceOrder) {return mapper.map (sourceOrder, Order.class); } @Override public DestinationCode convert (SourceCode sourceCode) {return mapper.map (sourceCode, DestinationCode.class); }}

4.3. MapStructConverter

Definicija MapStructa prilično je jednostavna jer se u potpunosti temelji na generiranju koda:

@Mapper javno sučelje MapStructConverter proširuje Converter {MapStructConverter MAPPER = Mappers.getMapper (MapStructConverter.class); @Mapiranje (source = "status", target = "orderStatus") @Override Pretvori narudžbu (SourceOrder sourceOrder); @Override DestinationCode pretvori (SourceCode sourceCode); }

4.4. JMapperConverter

JMapperConverter zahtijeva više posla. Nakon implementacije sučelja:

JMapperConverter javne klase implementira Converter {JMapper realLifeMapper; JMapper simpleMapper; javni JMapperConverter () {JMapperAPI api = novi JMapperAPI () .add (JMapperAPI.mappedClass (Order.class)); realLifeMapper = novi JMapper (Order.class, SourceOrder.class, api); JMapperAPI simpleApi = novi JMapperAPI () .add (JMapperAPI.mappedClass (DestinationCode.class)); simpleMapper = novi JMapper (DestinationCode.class, SourceCode.class, simpleApi); } @Override javni nalog za pretvorbu (SourceOrder sourceOrder) {return (Order) realLifeMapper.getDestination (sourceOrder); } @Override public DestinationCode convert (SourceCode sourceCode) {return (DestinationCode) simpleMapper.getDestination (sourceCode); }}

Također trebamo dodati @JMap napomene za svako polje ciljne klase. Također, JMapper ne može samostalno pretvoriti između tipova nabrajanja i zahtijeva da stvorimo prilagođene funkcije mapiranja:

@JMapConversion (od = "vrsta plaćanja", do = "vrsta plaćanja") javna pretvorba tipa plaćanja (com.baeldung.performancetests.model.source.PaymentType type) {Tip plaćanja PaymentType = null; prekidač (tip) {case KARTICA: vrsta plaćanja = Vrsta plaćanja.KARTICA; pauza; case CASH: paymentType = PaymentType.CASH; pauza; slučaj PRIJENOS: vrsta plaćanja = Vrsta plaćanja.PRIJENOS; pauza; } return typeType; }

4.5. ModelMapperConverter

ModelMapperConverter zahtijeva da pružimo samo klase koje želimo mapirati:

javna klasa ModelMapperConverter implementira Converter {private ModelMapper modelMapper; javni ModelMapperConverter () {modelMapper = novi ModelMapper (); } @Override pretvorba javne narudžbe (SourceOrder sourceOrder) {return modelMapper.map (sourceOrder, Order.class); } @Override public DestinationCode convert (SourceCode sourceCode) {return modelMapper.map (sourceCode, DestinationCode.class); }}

5. Jednostavno testiranje modela

Za ispitivanje performansi možemo koristiti Java Microbenchmark Harness, više informacija o tome kako ga koristiti možete pronaći u ovom članku.

Izradili smo zasebnu referentnu vrijednost za svaku Konverter s preciziranjem BenchmarkMode do Način rada.Sve.

5.1. Prosječno vrijeme

JMH je vratio sljedeće rezultate za prosječno vrijeme rada (što manje to bolje):

Naziv okviraProsječno vrijeme rada (u ms po operaciji)
MapStruct10 -5
JMapper10 -5
Orika0.001
ModelMapper0.001
Buldožer0.002

Ova usporedba jasno pokazuje da i MapStruct i JMapper imaju najbolje prosječno radno vrijeme.

5.2. Propusnost

U ovom načinu rada referentna vrijednost vraća broj operacija u sekundi. Dobili smo sljedeće rezultate (više je bolje) :

Naziv okviraPropusnost (u operacijama po ms)
MapStruct133719
JMapper106978
Orika1800
ModelMapper978
Buldožer471

U načinu propusnosti MapStruct je bio najbrži od testiranih okvira, a JMapper blizu sekunde.

5.3. SingleShotTime

Ovaj način omogućuje mjerenje vremena pojedinačne operacije od početka do kraja. Mjerilo je dalo sljedeći rezultat (manje je bolje):

Naziv okviraVrijeme pojedinačnog snimanja (u ms po operaciji)
JMapper0.015
MapStruct0.450
Buldožer2.094
Orika2.898
ModelMapper4.837

Ovdje vidimo da JMapper vraća bolji rezultat od MapStructa.

5.4. Vrijeme uzorka

Ovaj način omogućuje uzorkovanje vremena svake operacije. Rezultati za tri različita percentila izgledaju u nastavku:

Vrijeme uzorkovanja (u milisekundama po operaciji)
Naziv okvirap0,90p0,999p1.0
JMapper10-40.0012.6
MapStruct10-40.0013
Orika0.0010.0104
ModelMapper0.0020.0153.2
Buldožer0.0030.02125

Sva su mjerila pokazala da su MapStruct i JMapper dobar izbor, ovisno o scenariju.

6. Testiranje modela u stvarnom životu

Za testiranje performansi možemo koristiti Java Microbenchmark Harness, više informacija o tome kako ga koristiti možete pronaći u ovom članku.

Za svakog smo stvorili zasebnu referentnu vrijednost Konverter s preciziranjem BenchmarkMode do Način rada.Sve.

6.1. Prosječno vrijeme

JMH je vratio sljedeće rezultate za prosječno vrijeme rada (manje je bolje):

Naziv okviraProsječno vrijeme rada (u ms po operaciji)
MapStruct10 -4
JMapper10 -4
Orika0.004
ModelMapper0.059
Buldožer0.103

6.2. Propusnost

U ovom načinu rada referentna vrijednost vraća broj operacija u sekundi. Za svako mapiranje dobili smo sljedeće rezultate (više je bolje):

Naziv okviraPropusnost (u operacijama po ms)
JMapper7691
MapStruct7120
Orika281
ModelMapper19
Buldožer10

6.3. SingleShotTime

Ovaj način omogućuje mjerenje vremena pojedinačne operacije od početka do kraja. Mjerilo je dalo sljedeće rezultate (manje je bolje):

Naziv okviraVrijeme pojedinačnog snimanja (u ms po operaciji)
JMapper0.253
MapStruct0.532
Buldožer9.495
ModelMapper16.288
Orika18.081

6.4. Vrijeme uzorka

Ovaj način omogućuje uzorkovanje vremena svake operacije. Rezultati uzorkovanja podijeljeni su u percentile, predstavit ćemo rezultate za tri različita percentila p0,90, p0,999, i p1,00:

Vrijeme uzorkovanja (u milisekundama po operaciji)
Naziv okvirap0,90p0,999p1.0
JMapper10-30.00864
MapStruct10-30.01068
Orika0.0060.27832
ModelMapper0.0832.39897
Buldožer0.1464.526118

Iako su se točni rezultati jednostavnog primjera i primjera iz stvarnog života očito razlikovali, ali slijede više-manje isti trend. U oba primjera vidjeli smo blisko nadmetanje između JMappera i MapStructa za prvo mjesto.

6.5. Zaključak

Na temelju testiranja modela iz stvarnog života koje smo izveli u ovom odjeljku, možemo vidjeti da najbolja izvedba očito pripada JMapperu, iako je MapStruct na drugom mjestu. U istim testovima vidimo da se Dozer neprestano nalazi na dnu naše tablice rezultata, osim za SingleShotTime.

7. Sažetak

U ovom smo članku proveli testove performansi pet popularnih okvira za mapiranje zrna Java: ModelMapper, MapStruct, Orika, Dozer i JMapper.

Kao i uvijek, uzorci koda mogu se naći na GitHubu.


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