【问题标题】:Map multiple source fields to same type target fields with Mapstruct使用 Mapstruct 将多个源字段映射到相同类型的目标字段
【发布时间】:2016-06-09 03:22:32
【问题描述】:

考虑以下 POJO:

public class SchedulePayload {
    public String name;
    public String scheduler;
    public PeriodPayload notificationPeriod;
    public PeriodPayload schedulePeriod;
}

private class Lecture {
    public ZonedDateTime start;
    public ZonedDateTime end;
}

public class XmlSchedule {
    public String scheduleName;
    public String schedulerName;
    public DateTime notificationFrom;
    public DateTime notificationTo;
    public DateTime scheduleFrom;
    public DateTime scheduleTo;
}

public class PeriodPayload {
    public DateTime start;
    public DateTime finish;
}

使用 MapStruct,我创建了一个映射器,将 XmlSchedule 映射到 SchedulePayload。由于“业务”“逻辑”,我需要将notificationPeriod 和schedulePeriod 限制为Lecture 的start 和end 字段值。这是我想出的,使用另一个类:

@Mapper(imports = { NotificationPeriodHelper.class })
public interface ISchedulePayloadMapper
{
    @Mappings({
        @Mapping(target = "name", source = "scheduleName"),
        @Mapping(target = "scheduler", source = "schedulerName"),
        @Mapping(target = "notificationPeriod", expression = "java(NotificationPeriodHelper.getConstrainedPeriod(xmlSchedule, notificationFrom, notificationTo))"),
        @Mapping(target = "schedulePeriod", expression = "java(NotificationPeriodHelper.getConstrainedPeriod(xmlSchedule, scheduleFrom, scheduleTo))")
    })
    SchedulePayload map(XmlSchedule xmlSchedule, Lecture lecture);

}

有什么方法可以通过其他方式实现(即另一个映射器、装饰器等)?如何将多个值(xmlSchedule、lecture)传递给映射器?

【问题讨论】:

    标签: java mapping mapstruct


    【解决方案1】:

    您可以做的是创建一个@AfterMapping 方法来手动填充这些部分:

    @Mapper
    public abstract class SchedulePayloadMapper
    {
        @Mappings({
            @Mapping(target = "name", source = "scheduleName"),
            @Mapping(target = "scheduler", source = "schedulerName"),
            @Mapping(target = "notificationPeriod", expression = "java(NotificationPeriodHelper.getConstrainedPeriod(xmlSchedule, notificationFrom, notificationTo))"),
            @Mapping(target = "schedulePeriod", expression = "java(NotificationPeriodHelper.getConstrainedPeriod(xmlSchedule, scheduleFrom, scheduleTo))")
        })
        public abstract SchedulePayload map(XmlSchedule xmlSchedule, Lecture lecture);
    
        @AfterMapping
        protected void addPeriods(@MappingTarget SchedulePayload result, XmlSchedule xmlSchedule, Lecture lecture) {
            result.setNotificationPeriod(..);
            result.setSchedulePeriod(..);
        }
    }
    

    或者,您可以将 @AfterMapping 方法放在另一个在 @Mapper(uses = ..) 中引用的类中,或者您可以使用装饰器(使用 MapStruct 提供的机制,或者如果您使用依赖注入框架)。

    【讨论】:

    • @AfterMapping 似乎是一个干净的方法!谢谢!
    • 出于好奇,有没有办法处理不可变对象?
    • @RobertGabriel 因为最新的 (1.3.0.Beta1) MapStruct 可以使用构建器映射到不可变对象。在这个问题的答案中,这意味着您可以在@AfterMapping 中拥有SchedulePayload 的构建器
    • 是的,你是对的。昨天有个同事跟我说了同样的话。 :)
    • 请注意,在您的对象中使用构建器模式时,@MappingTarget 应该是 YourBuilder 类型,而不是您的响应类型!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 2019-03-14
    • 2020-12-20
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    相关资源
    最近更新 更多