MapStruct 忽略对象内列表内的 属性

MapStruct Ignore a property inside a list inside a Object

我有这个:

@Entity
public class Upgrade {
    ...
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "UPGRADE_PROJECT", joinColumns = @JoinColumn(name = "UPGRADE_ID"),
            inverseJoinColumns = @JoinColumn(name = "PROJECT_ID"))
    private List<Project> projects = new ArrayList<>();...}

public class Project {

    @ManyToMany(mappedBy = "projects")
    private List<Upgrade> upgrades = new ArrayList<>();

DTO 也类似于实体。

@Mapper(componentModel = "spring", uses = {VersionMapper.class, ProjectMapper.class,
        YearMonthMapper.class})
public interface UpgradeMapper {

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "acquired", dateFormat = "MMMM yyyy")
    UpgradeDTO upgradeToUpgradeDto(Upgrade upgrade, @Context CycleAvoidingMappingContext context);

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "acquired", dateFormat = "MM-yyyy")
    Upgrade upgradeDtoToUpgrade(UpgradeDTO upgradeDTO, @Context CycleAvoidingMappingContext context);

}

@Mapper(componentModel = "spring", uses = {UpgradeMapper.class, YearMonthMapper.class})
public interface ProjectMapper {

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "fromDate", dateFormat = "MMMM yyyy")
    @Mapping(target = "toDate", dateFormat = "MMMM yyyy")
    ProjectDTO projectToProjectDto(Project project, @Context CycleAvoidingMappingContext context);

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "fromDate", dateFormat = "MM-yyyy")
    @Mapping(target = "toDate", dateFormat = "MM-yyyy")
    Project projectDtoToProject(ProjectDTO projectDTO, @Context CycleAvoidingMappingContext context);
}

我像这样使用映射器:

    CycleAvoidingMappingContext cycleAvoidingMappingContext = new CycleAvoidingMappingContext();
    Upgrade upgrade = upgradeMapper.upgradeDtoToUpgrade(upgradeDTO, cycleAvoidingMappingContext);
    upgrade = setupAndSave(versionId, upgrade);
    return upgradeMapper.upgradeToUpgradeDto(upgrade, cycleAvoidingMappingContext);

我在创建升级时得到这个结果:

{
    "id": 1804,
    "version": {
        "id": 2007,
        "technology": {
            ...
        },
       ..
    },
    ...
    "projects": [
        {
            "id": 603,
            ...
    THIS SHOULD BE IGNORED
            "upgrades": [
                {
                    "id": 1703,

                    "projects": [
                        {
                            "id": 603,

                            "upgrades": [
                                1703,
                                {
                                    "id": 1704,

                                    "projects": [
                                       AND GOES ON AND ON
                                    ],

                                },
                                ..,
                                ..
                            ],
                            ..
                        },
                        {
                            "id": 604,
                            "upgrades": [
                                1703,
                                1704,
                                1803,
                                1804
                            ],
                            ..
                        }
                    ],
                    ..
                },
                1704,
                1803,
                1804
            ],
           ...
        },
        {
            "id": 604,
            "upgrades": [
                1703,
                1704,
                1803,
                1804
            ],
            ..
        }
    ],
    ..
}

我希望能够做这样的事情

public interface UpgradeMapper {

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "acquired", dateFormat = "MMMM yyyy")
    @Mapping(target = "projects.upgrades", ignore = true)
    UpgradeDTO upgradeToUpgradeDto(Upgrade upgrade, @Context CycleAvoidingMappingContext context);

但它不会工作,因为 projects 是一个列表而不是一个实体。

我目前的修复是:

@Mapper(componentModel = "spring", uses = {UpgradeMapper.class, YearMonthMapper.class})
public interface ProjectMapper {

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "fromDate", dateFormat = "MMMM yyyy")
    @Mapping(target = "toDate", dateFormat = "MMMM yyyy")
    @Mapping(target = "upgrades", ignore = true)
    ProjectDTO projectToProjectDto(Project project, @Context CycleAvoidingMappingContext context);

所以当我从数据库中获取项目实体并获取 DTO 时,DTO upgrades 为空。

我有办法在不损害关系另一方的情况下实现我的目标吗?

项目

{
    "id": 603,
    "upgrades": [],
    "createdAt": "10/June/2020  at 14:58:47"
}

升级(这是期望的行为)

{
    "id": 1804,
    "version": {
        "id": 2007,

    },
   ..
    "projects": [
        {
            "id": 603,
            ..
            "upgrades": [],
            "createdAt": "10/June/2020  at 14:58:47"
        },
        {
            "id": 604,
            ..
            "upgrades": [],
            "createdAt": "10/June/2020  at 14:59:59"
        }
    ],
    "createdAt": "10/June/2020  at 15:59:52"
}

编辑

根据 Filip 建议现在映射器看起来像这样:

@Mapper(componentModel = "spring", uses = {UpgradeMapper.class, YearMonthMapper.class})
public interface ProjectMapper {

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "fromDate", dateFormat = "MMMM yyyy")
    @Mapping(target = "toDate", dateFormat = "MMMM yyyy")
    ProjectDTO projectToProjectDto(Project project, @Context CycleAvoidingMappingContext context);

    @Mapping(target = "upgrades", ignore = true)
    @InheritConfiguration
    @Named("withoutUpgrades")
    ProjectDTO projectToProjectDtoWithoutUpgrades(Project project, @Context CycleAvoidingMappingContext context);

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "fromDate", dateFormat = "MM-yyyy")
    @Mapping(target = "toDate", dateFormat = "MM-yyyy")
    Project projectDtoToProject(ProjectDTO projectDTO, @Context CycleAvoidingMappingContext context);
}

@Mapper(componentModel = "spring", uses = {VersionMapper.class, ProjectMapper.class,
        YearMonthMapper.class})
public interface UpgradeMapper {

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "acquired", dateFormat = "MMMM yyyy")
    @Mapping(target = "projects", qualifiedByName = "withoutUpgrades")
    UpgradeDTO upgradeToUpgradeDto(Upgrade upgrade, @Context CycleAvoidingMappingContext context);

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "acquired", dateFormat = "MM-yyyy")
    Upgrade upgradeDtoToUpgrade(UpgradeDTO upgradeDTO, @Context CycleAvoidingMappingContext context);

}

它仍然不起作用,它仍然使用 projectToProjectDto 而不是 projectToProjectDtoWithoutUpgrades。怎么了?

您可以使用限定符忽略映射。

例如

@Mapper(componentModel = "spring", uses = {UpgradeMapper.class, YearMonthMapper.class})
public interface ProjectMapper {

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "fromDate", dateFormat = "MMMM yyyy")
    @Mapping(target = "toDate", dateFormat = "MMMM yyyy")
    ProjectDTO projectToProjectDto(Project project, @Context CycleAvoidingMappingContext context);

    @Mapping(target = "upgrades", ignore = "true"
    @InheritConfiguration
    @Named("withoutUpgrades")
    ProjectDTO projectToProjectDtoWithoutUpgrades(Project project, @Context CycleAvoidingMappingContext context);

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "fromDate", dateFormat = "MM-yyyy")
    @Mapping(target = "toDate", dateFormat = "MM-yyyy")
    Project projectDtoToProject(ProjectDTO projectDTO, @Context CycleAvoidingMappingContext context);
}
@Mapper(componentModel = "spring", uses = {VersionMapper.class, ProjectMapper.class,
        YearMonthMapper.class})
public interface UpgradeMapper {

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "acquired", dateFormat = "MMMM yyyy")
    @Mapping(target = "projects", qualifiedByName = "withoutUpgrades")
    UpgradeDTO upgradeToUpgradeDto(Upgrade upgrade, @Context CycleAvoidingMappingContext context);

    @Mapping(target = "createdAt", dateFormat = "dd/MMMM/yyyy [ 'at' HH:mm:ss]")
    @Mapping(target = "acquired", dateFormat = "MM-yyyy")
    Upgrade upgradeDtoToUpgrade(UpgradeDTO upgradeDTO, @Context CycleAvoidingMappingContext context);

}

这意味着当升级中 projects 的映射完成后,它将使用未经 withoutUpgrades 限定的映射来映射项目。