Spring 使用嵌套DTO将实体映射到DTO

Spring 使用嵌套DTO将实体映射到DTO,spring,hibernate,Spring,Hibernate,我有一个关系(繁重)数据库模型,其中包含很多表依赖项和外键。 为了简化前端的数据表示并隐藏数据库模式的复杂性,我们选择使用DTO 但是我们有嵌套DTO的DTO。我们有Mapper实现类来设置具有小型业务/功能逻辑的数据 问题是,映射器类调用映射器(等)是一种好的做法,还是让主类处理所有映射器类是一种最好的方法?(示例1或2) 例1: @Component public class ActorMapperImpl implements ActorMapper { @Autowired

我有一个关系(繁重)数据库模型,其中包含很多表依赖项和外键。 为了简化前端的数据表示并隐藏数据库模式的复杂性,我们选择使用DTO

但是我们有嵌套DTO的DTO。我们有Mapper实现类来设置具有小型业务/功能逻辑的数据

问题是,映射器类调用映射器(等)是一种好的做法,还是让主类处理所有映射器类是一种最好的方法?(示例1或2)

例1:

@Component
public class ActorMapperImpl implements ActorMapper {

    @Autowired
    private InsurerMapper insurerMapper;

    @Autowired
    private PersonMapper personMapper;

    @Autowired
    private CorrespondentMapper correspondentMapper;

    ....

    @Override
    public ActorDto mapToDto(Acteur actor) {
        final ActorDto actorDto;
        
        if (actor != null) {
            ....
            
            actorDto.setPerson(personMapper.personneToPersonDto(actor.getPersonne()));

            
            if (actor.getInsurer() != null) {
                actorDto.setInsurer(insurerMapper.entityToDto(actor.getInsurer()));
            } else if (actor.getCorrespondantAssureur() != null) {
                actorDto.setInsurer(correspondentMapper.correspondentToInsurerDto(actor.getCorrespondantAssureur()));
            }

            ....

            // intermediate
            final Intermediaire intermediate = actor.getIntermediaire();
            if (intermediate != null) {
                .....
                if (person != null) {
                    intermediateDto = personMapper.personneToPersonDto(person);
                    intermediateDto.setQuality(quality);
                } 
                .....
            }
        .....
例2:

@Service
public class FinancialSlipOrchestratorImpl implements FinancialSlipOrchestrator {

    .....
   

    @Autowired
    private FinancialSlipMapper financialSlipMapper;

    @Autowired
    private PersonMapper personMapper;

    

    ..... some public / private methods

    

    private FinancialSlipDto fullMapToDto(FinancialSlip financialSlip) {
        .....
    
    
        // Financial slip
        var financialSlipDto = financialSlipMapper.mapToDto(financialSlip);

        // person
        financialSlipDto.setIssuerPerson(personMapper.personneToPersonDto(financialSlip.getIssuerPerson()));
        
        ....

        // RIB
        financialSlipDto.setRib(ribMapper.mapToDto(financialSlip.getRib()));

        return financialSlipDto;
    }

我想说的是,一个映射器调用另一个映射器是可以的,并且认为这是一个完美的映射用例

我创建了这个库,以便在JPA模型和自定义接口或抽象类定义的模型之间进行简单的映射,类似于类固醇上的Spring数据投影。其思想是以您喜欢的方式定义目标结构(域模型),并通过JPQL表达式将属性(getter)映射到实体模型

在Blaze持久性实体视图中,您的用例的DTO模型可能如下所示:

@EntityView(Acteur.class)
public interface ActorDto {
    @IdMapping
    Long getId();
    String getName();
    PersonDto getPerson();
    default InsurerDto getInsurer() {
        return getMainInsurer() != null ? getMainInsurer(): getCorrespondantAssureur();
    }
    @Mapping("insurer")
    InsurerDto getMainInsurer();
    InsurerDto getCorrespondantAssureur();
    IntermediaireDto getIntermediaire();

    @EntityView(Person.class)
    interface PersonDto {
        @IdMapping
        Long getId();
        String getName();
    }
    @EntityView(Insurer.class)
    interface InsurerDto  {
        @IdMapping
        Long getId();
        String getName();
    }
    @EntityView(Intermediaire.class)
    interface IntermediaireDto {
        @IdMapping
        Long getId();
        String getName();
        Integer getQuality();
        PersonDto getPerson();
    }
}
查询是将实体视图应用于查询的问题,最简单的就是按id进行查询

ActorDto a=entityViewManager.find(entityManager,ActorDto.class,id)

Spring数据集成允许您像使用Spring数据投影一样使用它:

最好的是,它只会获取实际需要的数据


如果您也使用DTO刷新更改,您将很高兴听到Blaze持久化实体视图也以非常高效的方式支持这一点。这将允许您摆脱所有手动编写的映射器:)

不确定这里的最佳实践是什么-但我会选择手动编排。因此,如果循环依赖,您可以保持控制,并且不会遇到风险。谢谢您的回答