Clonar, mapear e transformar objetos de forma automática como se fosse escritos manualmente. Exemplo.: Conversão de Entity para DTO e vice-versa.
- Mapeamento checado em tempo de compilação
- Não usa reflections
- Usa somente anotação para configuração do código
- Baseado na JSR 269
- Fácil aprendizado
- Suporta mapeamentos customizados a nível de atributos
public class Pessoa {
private String nome;
private String sobrenome;
// + Getters and Setters
}
public class PessoaDTO {
private String nome;
private String sobrenome;
// + Getters and Setters
}
@Mapper
public interface PessoaMapper {
Pessoa toEntity(PessoaDTO dto);
PessoaDTO toDTO(Pessoa pessoa);
}
PessoaMapper pessoaMapper = Selma.builder(PessoaMapper.class).build();
PessoaDTO dto = pessoaMapper.toDTO(in);
Pessoa entity = pessoaMapper.toEntity(in);
@Mapper
public interface PessoaMapper {
// somente informando que o retorno é o mesmo que o parâmetro
Pessoa clonePessoa(Pessoa in);
}
Pessoa dto = pessoaMapper.clonePessoa(in);
public class Carro {
private String marca;
private String nomeComercial;
// + Getters and Setters
}
public class CarroDTO {
private String marca;
private String modelo;
// + Getters and Setters
}
@Mapper(withCustomFields = {
@Field({"modelo", "nomeComercial"})
})
public abstract class CarroMapper {
// + assinaturas necessárias
}
@Builder
public class Carro {
private String marca;
private String nomeComercial;
private Integer ano;
private String placa;
// + Getters and Setters
}
@Builder
public class CarroDTO {
private String marca;
private String modelo;
}
@Mapper(withIgnoreFields = {"ano", "placa"})
public abstract class CarroMapper {
// + assinaturas necessárias
}
public class Endereco {
private String logradouro;
private String bairro;
private String cep;
private String numero;
private String complemento;
}
public class Fornecedor {
private Integer id;
private String nome;
private String cnpj;
private Endereco endereco;
// + Getters and Setters
}
public class FornecedorDTO {
private Integer id;
private String nome;
private String cnpj;
private String logradouro;
private String bairro;
private String cep;
private String numero;
// + Getters and Setters
}
@Mapper(withCustomFields = {
@Field({"endereco.logradouro", "logradouro"}),
@Field({"endereco.bairro", "bairro"}),
@Field({"endereco.cep", "cep"}),
@Field({"endereco.numero", "numero"})
})
public interface FornecedorMapper {
// + assinaturas necessárias
}
@Mapper(
// + customizacoes quando necessárias
)
public interface FornecedorMapper {
Fornecedor toEntity(FornecedorDTO dto);
List<Fornecedor> toListEntity(List<FornecedorDTO> dto);
}
@Mapper(
withIgnoreFields = {"endereco", "matricula", "nascimento"},
withCustom = {
FornecedorMapper.class,
ClienteMapper.class,
TelefoneMapper.class
}
)
public interface PedidoMapper extends MapperBase<Pedido, PedidoDTO> {
// + assinaturas necessárias
}
@Mapper
public abstract class CarroMapper {
public Carro toEntity(CarroDTO dto) {
return new Carro(dto.getMarca(), dto.getModelo());
};
}
// ignora todas a propriedades divergentes
@Mapper(withIgnoreMissing = IgnoreMissing.ALL)
// ignora as propriedades que não existem no objeto de entrada
@Mapper(withIgnoreMissing = IgnoreMissing.SOURCE)
// ignora as propriedades que não existem no objeto de saída
@Map(withIgnoreMissing = IgnoreMissing.DESTINATION)
Testes executados em:
- OS: macOS Seria
- CPU: 3.1 GHz Intel Core i7, 2 cores, L2 Cache (per Core): 256 KB, L3 Cache: 4 MB
- RAM: 16 GB 1867 MHz DDR3
- JVM: Oracle 1.8.0_74-b02 64 bits
Benchmark | Mode | Samples | Score | Margin error (+/-) | Units |
---|---|---|---|---|---|
Manual | thrpt | 200 | 16 262 690 | 74 221 | ops/s |
Selma | thrpt | 200 | 15 773 717 | 99 740 | ops/s |
MapStruct | thrpt | 200 | 14 518 416 | 179 884 | ops/s |
JMapper | thrpt | 200 | 14 492 381 | 82 798 | ops/s |
Orika | thrpt | 200 | 3 550 464 | 30 533 | ops/s |
ModelMaper | thrpt | 200 | 256 959 | 2 413 | ops/s |
Dozer | thrpt | 200 | 86 607 | 488 | ops/s |
Legenda: Quanto maior o score melhor
Total tempo: 00:48:33