Quantcast
Channel: Planeta Código
Viewing all articles
Browse latest Browse all 2699

Blog Bitix: Copiar datos de un tipo de objeto a otro con ModelMapper

$
0
0

Las clases DTO son clases usadas como contenedores de datos sin ninguna lógica o con muy poca, se construyen con datos copiados de otras clases. Un uso de estas clases DTO es para evitar emplear el uso del patrón Open Session in View ya que aunque ofrece algunos beneficios también tiene algunos inconvenientes. La librería ModelMapper permite realizar los copiados de datos de un objeto origen a una nueva instancia destino de otra clase.

Java

En ocasiones es necesario copiar datos de un tipo de objeto a otro tipo, no es una operación complicada basta con llamar al método getter de la propiedad a copiar para obtener su valor del objeto origen y posteriormente llamar al setter para establecer el valor en objeto destino. Aún siendo una operación sencilla es tediosa y puede complicarse si se han de copiar listas de objetos y si esos objetos a copiar tienen referencias a otros objetos que también hay que copiar. Si además esta es una operación común en el código es conveniente utilizar una librería específica para este propósito, una de ellas es ModelMapper.

ModelMapper es una librería Java para copiar o mapear propiedades de un tipo de objeto a otro tipo de objeto, permitiendo copiar también los datos de las referencias a los objetos que contengan. Soporta diferentes convenciones, copiados explícitos, conversiones y proveedores para construir los objetos destino e integraciones con diferentes librerías, una de ellas jOOQ.

Un posible caso de uso es para evitar emplear el patrón Open Session in View ya que tiene varios inconvenientes. Con una librería como ModelMapper es posible hacer uso de simples objetos contenedores de datos en la vista copiando los datos de las entidades a los objetos DTO. O si para obtener los datos de la vista en vez de usar una librería como Hibernate se opta por una librería como jOOQ permitir copiar los datos de los registros de jOOQ a los mismos DTOs.

El siguiente ejemplo se compone de tres clases que tienen relaciones entre ellas, estas clases podrían ser las entidades si se persistiesen en base de datos con Hibernate.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
packageio.github.picodotdev.blogbitix.modelmapper.classes;publicclassOrder{    privateCustomercustomer;    privateAddressbillingAddress;    publicOrder(Customercustomer,AddressbillingAddress){        this.customer=customer;        this.billingAddress=billingAddress;    }    publicCustomergetCustomer(){        returncustomer;    }    publicAddressgetBillingAddress(){        returnbillingAddress;    }}
Order.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
packageio.github.picodotdev.blogbitix.modelmapper.classes;publicclassCustomer{    privateStringfirstName;    privateStringlastName;    publicCustomer(StringfirstName,StringlastName){        this.firstName=firstName;        this.lastName=lastName;    }    publicStringgetFirstName(){        returnfirstName;    }    publicStringgetLastName(){        returnlastName;    }}
Customer.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
packageio.github.picodotdev.blogbitix.modelmapper.classes;publicclassAddress{    privateStringstreet;    privateStringcity;    publicAddress(Stringstreet,Stringcity){        this.street=street;        this.city=city;    }    publicStringgetStreet(){        returnstreet;    }    publicStringgetCity(){        returncity;    }}
Address.java

La clase DTO es simplemente una nueva clase POJO que contiene los datos de las clases anteriores, para evitar el patrón Open Session in View la vista recibiría una instancia de esta clase.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
packageio.github.picodotdev.blogbitix.modelmapper.classes;publicclassOrderDTO{    privateStringcustomerFirstName;    privateStringcustomerLastName;    privateStringbillingAddressStreet;    privateStringbillingAddressCity;    publicStringgetCustomerFirstName(){        returncustomerFirstName;    }    publicvoidsetCustomerFirstName(StringcustomerFirstName){        this.customerFirstName=customerFirstName;    }    publicStringgetCustomerLastName(){        returncustomerLastName;    }    publicvoidsetCustomerLastName(StringcustomerLastName){        this.customerLastName=customerLastName;    }    publicStringgetBillingAddressStreet(){        returnbillingAddressStreet;    }    publicvoidsetBillingAddressStreet(StringbillingAddressStreet){        this.billingAddressStreet=billingAddressStreet;    }    publicStringgetBillingAddressCity(){        returnbillingAddressCity;    }    publicvoidsetBillingAddressCity(StringbillingAddressCity){        this.billingAddressCity=billingAddressCity;    }}
OrderDTO.java

En esta aplicación de Spring Boot se construye una instancia de la clase ModelMapper y posteriormente con su configuración y convenciones por defecto realiza el copiado de datos de una instancia de la clase Order a una nueva instancia de la clase OrderDTO. En la salida del programa en la consola se muestran los valores de las propiedades de OrderDTO copiadas de la clase Order.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
packageio.github.picodotdev.blogbitix.modelmapper;importio.github.picodotdev.blogbitix.modelmapper.classes.Address;importio.github.picodotdev.blogbitix.modelmapper.classes.Customer;importio.github.picodotdev.blogbitix.modelmapper.classes.Order;importio.github.picodotdev.blogbitix.modelmapper.classes.OrderDTO;importorg.modelmapper.ModelMapper;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.CommandLineRunner;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.context.annotation.Bean;@SpringBootApplicationpublicclassMainimplementsCommandLineRunner{@AutowiredprivateModelMappermodelMapper;@BeanModelMappermodelMapper(){returnnewModelMapper();}@Overridepublicvoidrun(String...args)throwsException{Customercustomer=newCustomer("Francisco","Ibáñez");AddressbilligAddress=newAddress("c\\ Rue del Percebe, 13","Madrid");Orderorder=newOrder(customer,billigAddress);OrderDTOorderDTO=modelMapper.map(order,OrderDTO.class);System.out.printf("Customer First Name: %s%n",orderDTO.getCustomerFirstName());System.out.printf("Customer Last Name: %s%n",orderDTO.getCustomerLastName());System.out.printf("Billing Address Street: %s%n",orderDTO.getBillingAddressStreet());System.out.printf("Billing Address City: %s%n",orderDTO.getBillingAddressCity());}publicstaticvoidmain(String[]args){SpringApplication.run(Main.class,args);}}
Main.java
1
2
3
4
Customer First Name: Francisco
Customer Last Name: Ibáñez
Billing Address Street: c\ Rue del Percebe, 13
Billing Address City: Madrid
System.out

El archivo de contrucción Gradle contiene la dependencia de ModelMapper.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
plugins{    id'java'    id'application'}group='io.github.picodotdev.blogbitix.modelmapper'version='1.0'java{    sourceCompatibility=JavaVersion.VERSION_11}application{    mainClass='io.github.picodotdev.blogbitix.modelmapper.Main'}repositories{    mavenCentral()}dependencies{    implementationplatform('org.springframework.boot:spring-boot-dependencies:2.3.0.RELEASE')    implementation'org.springframework.boot:spring-boot-starter'    implementation'org.modelmapper:modelmapper:2.3.7'}
build.gradle
Terminal

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:
./gradlew run


Viewing all articles
Browse latest Browse all 2699