Convert DTO to Entity Java

Asked

Viewed 3,382 times

1

I have the following problem, I am trying to create a method that converts DTO’s for Entity’s and vice versa until the moment I arrived at the following method that converts perfectly when they are compatible attributes String for String, Long for Long etc. Of course being the premise that the types I want to convert are always the same.

public static <T> void ConvertDtoToEntity(T dto, T entity){
    Field[] entitycampos = entity.getClass().getDeclaredFields();
    Field[] dtocampos = dto.getClass().getDeclaredFields();

    for (Field entityfield : entitycampos) {
        entityfield.setAccessible(true);
        for (Field dtofield : dtocampos) { 
            dtofield.setAccessible(true);               
            if(!entityfield.getName().equals("serialVersionUID") 
                && entityfield.getName().equals(dtofield.getName()))
            {
                try {
                    entityfield.set(entity, dtofield.get(dto));
                    break;
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Only the problem is time to convert List, Set and other dtos or other entitys that are within that dto. EX DTO that Convert perfectly for an Entity:

public class CupomHistoricoDto implements Serializable{

    private static final long serialVersionUID = 1L;

    private BigDecimal seqcupomhistorico;
    private int quantidade;
    private Date data;
    private long nroempresa;

EX Entity that Convert perfectly for a dto:

public class CupomHistoricoEntity implements Serializable {

    private static final long serialVersionUID = 1L;    

    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    @Column(name = "SEQCUPOMHISTORICO", unique = true, nullable = false)
    private BigDecimal seqcupomhistorico;

    @Column(name = "QUANTIDADE", nullable = false)
    private int quantidade;

    @Column(name = "DATA", nullable = false)
    private Date data;

    @Column(name = "NROEMPRESA", nullable = false)
    private long nroempresa;

EX DTO that is not converting to an Entity

public class CupomHistoricoDto implements Serializable{

    private static final long serialVersionUID = 1L;

    private BigDecimal seqcupomhistorico;
    private int quantidade;
    private Date data;
    private long nroempresa;
    private CupomHistoricoDetalheDto detalhe; 

EX Entity

public class CupomHistoricoEntity implements Serializable {

    private static final long serialVersionUID = 1L;    

    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    @Column(name = "SEQCUPOMHISTORICO", unique = true, nullable = false)
    private BigDecimal seqcupomhistorico;

    @Column(name = "QUANTIDADE", nullable = false)
    private int quantidade;

    @Column(name = "DATA", nullable = false)
    private Date data;

    @Column(name = "NROEMPRESA", nullable = false)
    private long nroempresa;

    @OneToOne  
    @JoinColumn(name = "seqdetalhe", referencedColumnName = "SEQDETALHE")
    private CupomHistoricoDetalheEntity detalhe;

Would anyone have any idea how to implement this method or have done something similar.

NOTE: I’m testing if I can do what I want using apache Beanutils.

  • You’re trying to clone objects, right? To make a "deep cloning" (deep clone), you can serialize and deserialize an object or you can use a library specializing in cloning. See: http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/SerializationUtils.html and http://code.google.com/p/cloning/. I don’t understand where "Entity" and "DTO" come into this story - see that an untapped enitity can eventually be considered a DTO. If you explain your goal maybe we can point out simpler solution.

  • @Caffé Here in the company we have the Entity layer and Dto and we use Dto to carry the information, and in the service we convert to dto~Entity to work with the base and Entity~dto to carry with the information, We do so because we use many fields in dtos that are naughty in Entity. This method of work is already an old way of working here, only now they want to speed up the conversion of objects, the method I did above makes a part but not for the objects inside them. I looked at the apache but he also does not answer, he does what I did above.

  • Doesn’t do what you do because he makes one deep Cloning (as long as all classes are serializable) while you are making a Shallow Cloning. Anyway the most suitable is the cloning more performative that I indicated in the second link, since it does not require the classes to be serialized and since serialize and deserialize is very expensive.

3 answers

3

I believe the best thing for your case is to do it manually. Create your own mechanism to do this conversion, once you know perfectly well the Dtos and Entitys and as you said yourself: "we use many fields in dtos that are naughty in Entity". With a mechanism created by you and specific you can control what passes from DTO to Entity and vice versa since not everything from DTO has to pass to respective Entity. Do something more or less like this:

  1. Create an interface

    public interface Conveter
    {   
       public GenericDTO convertFromEntity(GenericEntity entity);
       public GenericEntity convertFromDTO(GenericDTO dto);
    }
    
  2. Create implementations for each of your types (DTO-Entity)

     public CupomHistoricoConverter implements Converter
     {
        @Override
        public GenericDTO convertFromEntity(GenericEntity entity)
        {
          // Faça aqui a conversão manual campo a campo de entity para dto
        }
    
        @Override
        public GenericEntity convertFromDTO(GenericDTO dto)
        {
          // Faça aqui a conversão manual campo a campo de  dto para entity
        }
    } 
    

It’s a bit of a hassle, but it’s better because then you have complete control of what’s happening and what’s really to be converted.

I hope I’ve helped

1

Following the reasoning of the previous solution, we can still leave parameterized to avoid casting when implementing the converters.

public interface Converter<DTO extends GenericDTO, ENT extends GenericEntity> {

        public DTO convertFromEntity(ENT entity);
        public ENT convertFromDTO(DTO dto);

}



public CupomHistoricoConverter implements Converter <CupomHistoricoDTO, CupomHistoricoEntity> 
 {
    @Override
    public CupomHistoricoDTO convertFromEntity(CupomHistoricoEntity entity)
    {
      // Faça aqui a conversão manual campo a campo de entity para dto
    }

    @Override
    public CupomHistoricoEntity convertFromDTO(CupomHistoricoDTO dto)
    {
      // Faça aqui a conversão manual campo a campo de  dto para entity
    }
} 

-1

Use the Dozer

<dependency> <groupId>net.sf.dozer</groupId> <artifactId>dozer</artifactId> <version>5.4.0</version> </dependency>

Mapper mapper = new DozerBeanMapper(); EntidadeDestino entidade = mapper.map(entidadeOrigem, EntidadeDestino.class);

  • Consider adding a brief explanation of why your answer solves the problem.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.