Guia para JMapper
*1. Visão geral *
Neste tutorial, exploraremos JMapper -* uma estrutura de mapeamento rápida e fácil de usar. *
Discutiremos diferentes maneiras de configurar o JMapper, como executar conversões personalizadas, bem como o mapeamento relacional.
===* 2. Configuração do Maven *
Primeiro, precisamos adicionar a JMapper dependency ao nosso pom.xml:
<dependency>
<groupId>com.googlecode.jmapper-framework</groupId>
<artifactId>jmapper-core</artifactId>
<version>1.6.0.1</version>
</dependency>
===* 3. Modelos de origem e destino *
Antes de chegarmos à configuração, vamos dar uma olhada nos beans simples que vamos usar neste tutorial.
Primeiro, aqui está o nosso bean de origem - um User básico:
public class User {
private long id;
private String email;
private LocalDate birthDate;
}
E nosso bean de destino, _UserDto: _
public class UserDto {
private long id;
private String username;
}
*Usaremos a biblioteca para mapear atributos do nosso bean de origem _User_ para o nosso bean de destino _UserDto _.*
Existem três maneiras de configurar o JMapper: usando a API, anotações e configuração XML.
Nas seções a seguir, abordaremos cada uma delas.
*4. Usando a API *
Vamos ver como configurar o JMapper usando a API.
Aqui, não precisamos adicionar nenhuma configuração às nossas classes de origem e destino. Em vez disso, toda a* configuração pode ser feita usando _ JMapperAPI *, _, o que o torna o método de configuração mais flexível:
@Test
public void givenUser_whenUseApi_thenConverted(){
JMapperAPI jmapperApi = new JMapperAPI()
.add(mappedClass(UserDto.class)
.add(attribute("id").value("id"))
.add(attribute("username").value("email")));
JMapper<UserDto, User> userMapper = new JMapper<>
(UserDto.class, User.class, jmapperApi);
User user = new User(1L,"[email protected]", LocalDate.of(1980,8,20));
UserDto result = userMapper.getDestination(user);
assertEquals(user.getId(), result.getId());
assertEquals(user.getEmail(), result.getUsername());
}
Aqui, usamos o método mappedClass () _ para definir nossa classe mapeada _UserDto. Em seguida, usamos o método _attribute () _ para definir cada atributo e seu valor mapeado.
Em seguida, criamos um objeto JMapper com base na configuração e usamos seu método getDestination () _ para obter o resultado _UserDto.
*5. Usando anotações *
Vamos ver como* podemos usar a anotação _ @ JMap_ para configurar nosso mapeamento *:
public class UserDto {
@JMap
private long id;
@JMap("email")
private String username;
}
E aqui está como usaremos nosso JMapper:
@Test
public void givenUser_whenUseAnnotation_thenConverted(){
JMapper<UserDto, User> userMapper = new JMapper<>(UserDto.class, User.class);
User user = new User(1L,"[email protected]", LocalDate.of(1980,8,20));
UserDto result = userMapper.getDestination(user);
assertEquals(user.getId(), result.getId());
assertEquals(user.getEmail(), result.getUsername());
}
Observe que, para o atributo id, não precisamos fornecer um nome de campo de destino, pois é o mesmo nome do bean de origem, enquanto que para o campo username mencionamos que ele corresponde ao campo email na classe User.
Então, precisamos apenas passar os beans de origem e de destino para o nosso JMapper - nenhuma configuração adicional é necessária.
No geral, esse método é conveniente, pois utiliza a menor quantidade de código.
*6. Usando a configuração XML *
Também podemos usar a configuração XML para definir nosso mapeamento.
Aqui está nossa configuração XML de amostra em user_jmapper.xml:
<jmapper>
<class name="com..jmapper.UserDto">
<attribute name="id">
<value name="id"/>
</attribute>
<attribute name="username">
<value name="email"/>
</attribute>
</class>
</jmapper>
E precisamos passar nossa configuração XML para JMapper:
@Test
public void givenUser_whenUseXml_thenConverted(){
JMapper<UserDto, User> userMapper = new JMapper<>
(UserDto.class, User.class,"user_jmapper.xml");
User user = new User(1L,"[email protected]", LocalDate.of(1980,8,20));
UserDto result = userMapper.getDestination(user);
assertEquals(user.getId(), result.getId());
assertEquals(user.getEmail(), result.getUsername());
}
Também podemos passar a configuração XML como String diretamente para JMapper em vez de um nome de arquivo.
===* 7. Mapeamento Global *
*Podemos tirar vantagem do mapeamento global se tivermos vários campos com o mesmo nome nos beans de origem e de destino.*
Por exemplo, se tivermos um UserDto1 que possui dois campos, id e email:
public class UserDto1 {
private long id;
private String email;
//standard constructor, getters, setters
}
O mapeamento global será mais fácil de usar, pois eles são mapeados para campos com o mesmo nome no bean de origem User.
7.1 Usando a API
Para a configuração JMapperAPI, usaremos _global () _:
@Test
public void givenUser_whenUseApiGlobal_thenConverted() {
JMapperAPI jmapperApi = new JMapperAPI()
.add(mappedClass(UserDto.class).add(global())) ;
JMapper<UserDto1, User> userMapper1 = new JMapper<>
(UserDto1.class, User.class,jmapperApi);
User user = new User(1L,"[email protected]", LocalDate.of(1980,8,20));
UserDto1 result = userMapper1.getDestination(user);
assertEquals(user.getId(), result.getId());
assertEquals(user.getEmail(), result.getEmail());
}
7.2 Usando anotações
Para a configuração da anotação, usaremos _ @ JGlobalMap_ no nível da classe:
@JGlobalMap
public class UserDto1 {
private long id;
private String email;
}
E aqui está um teste simples:
@Test
public void whenUseGlobalMapAnnotation_thenConverted(){
JMapper<UserDto1, User> userMapper= new JMapper<>(
UserDto1.class, User.class);
User user = new User(
1L,"[email protected]", LocalDate.of(1980,8,20));
UserDto1 result = userMapper.getDestination(user);
assertEquals(user.getId(), result.getId());
assertEquals(user.getEmail(), result.getEmail());
}
7.3. Configuração XML
E para a configuração XML, temos o elemento _ <global/> _:
<jmapper>
<class name="com..jmapper.UserDto1">
<global/>
</class>
</jmapper>
E depois passe o nome do arquivo XML:
@Test
public void givenUser_whenUseXmlGlobal_thenConverted(){
JMapper<UserDto1, User> userMapper = new JMapper<>
(UserDto1.class, User.class,"user_jmapper1.xml");
User user = new User(1L,"[email protected]", LocalDate.of(1980,8,20));
UserDto1 result = userMapper.getDestination(user);
assertEquals(user.getId(), result.getId());
assertEquals(user.getEmail(), result.getEmail());
}
*8. Conversões personalizadas *
Agora, vamos ver como aplicar uma conversão personalizada usando JMapper.
Temos um novo campo age em nosso UserDto, que precisamos calcular a partir do atributo User birthDate:
public class UserDto {
@JMap
private long id;
@JMap("email")
private String username;
@JMap("birthDate")
private int age;
@JMapConversion(from={"birthDate"}, to={"age"})
public int conversion(LocalDate birthDate){
return Period.between(birthDate, LocalDate.now())
.getYears();
}
}
Portanto,* usamos _ @ JMapConversion_ para aplicar uma conversão complexa *do UserData de nascimento do usuário ao atributo _UserDto’s age. Portanto, o campo age será calculado quando mapearmos User para UserDto:
@Test
public void whenUseAnnotationExplicitConversion_thenConverted(){
JMapper<UserDto, User> userMapper = new JMapper<>(
UserDto.class, User.class);
User user = new User(
1L,"[email protected]", LocalDate.of(1980,8,20));
UserDto result = userMapper.getDestination(user);
assertEquals(user.getId(), result.getId());
assertEquals(user.getEmail(), result.getUsername());
assertTrue(result.getAge() > 0);
}
===* 9. Mapeamento relacional *
Por fim, discutiremos o mapeamento relacional.* Com esse método, precisamos definir nosso JMapper usando uma classe de destino a cada vez. *
Se já conhecemos as classes de destino, podemos defini-las para cada campo mapeado e usar RelationalJMapper.
Neste exemplo, temos um bean de origem User:
public class User {
private long id;
private String email;
}
E dois beans de destino UserDto1:
public class UserDto1 {
private long id;
private String username;
}
E UserDto2:
public class UserDto2 {
private long id;
private String email;
}
Vamos ver como tirar proveito do nosso RelationalJMapper.
====* 9.1 Usando a API *
Para nossa configuração de API, podemos definir classes de destino para cada atributo usando _targetClasses () _:
@Test
public void givenUser_whenUseApi_thenConverted(){
JMapperAPI jmapperApi = new JMapperAPI()
.add(mappedClass(User.class)
.add(attribute("id")
.value("id")
.targetClasses(UserDto1.class,UserDto2.class))
.add(attribute("email")
.targetAttributes("username","email")
.targetClasses(UserDto1.class,UserDto2.class)));
RelationalJMapper<User> relationalMapper = new RelationalJMapper<>
(User.class,jmapperApi);
User user = new User(1L,"[email protected]");
UserDto1 result1 = relationalMapper
.oneToMany(UserDto1.class, user);
UserDto2 result2 = relationalMapper
.oneToMany(UserDto2.class, user);
assertEquals(user.getId(), result1.getId());
assertEquals(user.getEmail(), result1.getUsername());
assertEquals(user.getId(), result2.getId());
assertEquals(user.getEmail(), result2.getEmail());
}
Observe que, para cada classe de destino, precisamos definir o nome do atributo de destino.
O RelationalJMapper leva apenas uma classe - a classe mapeada.
====* 9.2. Usando anotações *
Para a abordagem de anotação, definiremos as classes também:
public class User {
@JMap(classes = {UserDto1.class, UserDto2.class})
private long id;
@JMap(
attributes = {"username", "email"},
classes = {UserDto1.class, UserDto2.class})
private String email;
}
Como de costume, nenhuma configuração adicional é necessária quando usamos anotações:
@Test
public void givenUser_whenUseAnnotation_thenConverted(){
RelationalJMapper<User> relationalMapper
= new RelationalJMapper<>(User.class);
User user = new User(1L,"[email protected]");
UserDto1 result1 = relationalMapper
.oneToMany(UserDto1.class, user);
UserDto2 result2= relationalMapper
.oneToMany(UserDto2.class, user);
assertEquals(user.getId(), result1.getId());
assertEquals(user.getEmail(), result1.getUsername());
assertEquals(user.getId(), result2.getId());
assertEquals(user.getEmail(), result2.getEmail());
}
====* 9.3 Configuração XML *
Para a configuração XML, usamos _ <classes> _ para definir as classes de destino para cada atributo.
Aqui está o nosso user_jmapper2.xml:
<jmapper>
<class name="com..jmapper.relational.User">
<attribute name="id">
<value name="id"/>
<classes>
<class name="com..jmapper.relational.UserDto1"/>
<class name="com..jmapper.relational.UserDto2"/>
</classes>
</attribute>
<attribute name="email">
<attributes>
<attribute name="username"/>
<attribute name="email"/>
</attributes>
<classes>
<class name="com..jmapper.relational.UserDto1"/>
<class name="com..jmapper.relational.UserDto2"/>
</classes>
</attribute>
</class>
</jmapper>
E então passe o arquivo de configuração XML para RelationalJMapper:
@Test
public void givenUser_whenUseXml_thenConverted(){
RelationalJMapper<User> relationalMapper
= new RelationalJMapper<>(User.class,"user_jmapper2.xml");
User user = new User(1L,"[email protected]");
UserDto1 result1 = relationalMapper
.oneToMany(UserDto1.class, user);
UserDto2 result2 = relationalMapper
.oneToMany(UserDto2.class, user);
assertEquals(user.getId(), result1.getId());
assertEquals(user.getEmail(), result1.getUsername());
assertEquals(user.getId(), result2.getId());
assertEquals(user.getEmail(), result2.getEmail());
}
===* 10. Conclusão*
Neste tutorial, aprendemos diferentes maneiras de configurar o JMapper e como executar uma conversão personalizada.
O código fonte completo dos exemplos pode ser encontrado em over no GitHub.