0

I'm facing a problem for mapping entities. I actually extend all my entities why this class :

@MappedSuperclass
@Data
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(
        value = {"logcreatedAt", "logupdatedAt"},
        allowGetters = true
)
public abstract class AuditModel implements Serializable {
    
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    @Column(name = "log_created_at", nullable = false, updatable = false)
    @CreatedDate
    private Date logCreatedAt = new Date();

    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    @Column(name = "log_updated_at", nullable = false)
    @LastModifiedDate
    private Date logUpdatedAt = new Date();
}

The problem, that i have is this one :

1) The destination property com.example.jpa.dto.HistoriqueDeploiementReadingDTO.setLog_updated_at() matches multiple source property hierarchies:

    com.example.jpa.model.AuditModel.getLogUpdatedAt()
    com.example.jpa.model.AuditModel.getLogCreatedAt()
    com.example.jpa.model.HistoriqueDeploiement.getService()/com.example.jpa.model.AuditModel.getLogUpdatedAt()
    com.example.jpa.model.HistoriqueDeploiement.getService()/com.example.jpa.model.AuditModel.getLogCreatedAt()
    com.example.jpa.model.HistoriqueDeploiement.getNamespace()/com.example.jpa.model.AuditModel.getLogUpdatedAt()
    com.example.jpa.model.HistoriqueDeploiement.getNamespace()/com.example.jpa.model.AuditModel.getLogCreatedAt()

I understand what's wrong for the mapper, but i don't find any solution for that... This stack doesn't help me at all : ModelMapper: matches multiple source property hierarchies

My mapper :

@Service
@Configuration
@Slf4j
public class MappingHistoriqueToDTO {

    @Autowired
    private HistoriqueDeploiementRepository historiqueDeploiementRepository;
    
    @Autowired
    private ModelMapper modelMapper;

    @Bean
    public ModelMapper modelMapper() {
       ModelMapper modelMapper = new ModelMapper();
       return modelMapper;
    }
    
    public List<HistoriqueDeploiementReadingDTO> findAllMapping() {
       return ((List<HistoriqueDeploiement>) historiqueDeploiementRepository
                .findAll())
                .stream()
                .map(this::convertToHistoriqueDeploiementReadingDTO)
                .collect(Collectors.toList());
    }

    private HistoriqueDeploiementReadingDTO convertToHistoriqueDeploiementReadingDTO(HistoriqueDeploiement historiqueDeploiement) { 
        modelMapper.getConfiguration()
                .setMatchingStrategy(MatchingStrategies.LOOSE);
        HistoriqueDeploiementReadingDTO historiqueDeploiementReadingDTO = modelMapper
                .map(historiqueDeploiement, HistoriqueDeploiementReadingDTO.class); 
        log.info("[Mapping] HistoriqueDeploiement -> HistoriqueDeploiementReadingDTO");
        return historiqueDeploiementReadingDTO;
    }
}

I would like that the mapper get the value of getLogUpdatedAt() from the historiquedeploiement entity and not from Namespace or Service.

Thanks !

Kévin
  • 497
  • 10
  • 37
  • So your `HistoriqueDeploiement` extends `AuditModel`? Can you show it and also the DTO? – pirho Nov 03 '20 at 16:55
  • Yes it was extending that, i found that i was not the only person to have this problem. One solution was found by others, but modelmapper throw warning since java 8, and it has not been corrected by their team ( tested in java 14)? I posted my actual solution – Kévin Nov 03 '20 at 17:05
  • There might (stress might) have been a nice MM solution if you only would have provided the code needed to reproduce & test instead of all the irrelevant code :) – pirho Nov 03 '20 at 18:17

1 Answers1

1

I solved it by doing my own mapping like that. I don't use modelmapper anymore

public List<CheckConfigDTO> findAllMapping() {
        log.info("[Mapping] CheckConfig -> CheckConfigDTO");
        return ((List<CheckConfig>) checkConfigRepository
                .findAll())
                .stream()
                .map(this::convertToCheckConfigDTO)
                .collect(Collectors.toList());
    }
    

    private CheckConfigDTO convertToCheckConfigDTO(CheckConfig checkConfig) {       
        CheckConfigDTO checkConfigDTO = new CheckConfigDTO();
        checkConfigDTO.setId(checkConfig.getId());
        checkConfigDTO.setNamespace(checkConfig.getNamespace().getNamespace());
        checkConfigDTO.setService(checkConfig.getService().getService());
        checkConfigDTO.setType_verification(checkConfig.getTypeVerification());
        checkConfigDTO.setStatus(checkConfig.getStatus());
        checkConfigDTO.setStatus_complementaire(checkConfig.getStatusComplementaire());
        checkConfigDTO.setDetails(checkConfig.getDetails());
        checkConfigDTO.setAction_by(checkConfig.getActionBy());     
        checkConfigDTO.setLog_created_at(checkConfig.getLogCreatedAt());
        checkConfigDTO.setLog_updated_at(checkConfig.getLogUpdatedAt());        
        return checkConfigDTO;
    } 

Kévin
  • 497
  • 10
  • 37
  • We can do it manually but this is not going to help in enterprise level application where we need to handle huge DTOs with hundreds of variables. – Learn More Mar 30 '22 at 07:51