自动映射除一个字段外的所有字段,该字段应通过其他函数传递

Auto-map all fields except one, which should be passed through some other function

我如何使用 Mapstruct 创建一个映射器来自动映射除了一个(或两个、三个等)字段之外的所有字段,这些字段应该通过一些自定义映射逻辑传递?

映射器

@Mapper
public interface MyEntityMapper
{
    MyEntityMapper INSTANCE = Mappers.getMapper(MyEntityMapper.class);

    @Mappings(
        {
            @Mapping(source = "createdByPerson.id", target = "createdByPersonId"),
        })
    MyEventPayload toEventPayload(MyEntity entity);
}

如果我有一个 someString 字段需要首先完成一些自定义映射日志记录,我该怎么做?我看到 @Mappingargument 选项,但是在注释中的字符串中编写 java 代码似乎有点疯狂!

我希望做这样的事情:

@MappingFor(MyEntity.class, "someString")
default String mapSomeString(String value) {
    return value + " custom mapping ";
}

更新

我找到了 @AfterMapping 并使用了它,例如:

@AfterMapping
public void mapSomeString(MyEntity entity, MyEventPayload payload) {
    // do fancy stuff here
}

但我仍然很好奇您是否可以提供每个字段的后映射/自定义映射功能。

你看过Expressions的MapStruct吗?

这是来自文档的示例:

@Mapping(target = "timeAndFormat",
     expression = "java( new org.sample.TimeAndFormat( s.getTime(), s.getFormat() ) )")

您可以使用 class 构造函数或方法来代替 new org.sample.TimeAndFormat...

我最终使用了@AfterMapping 例如:

@AfterMapping
public void mapSomeString(MyEntity entity, MyEventPayload payload) {
    // do fancy stuff here
}

如果您想以特定方式映射单个字段,您可以使用 Mapping methods selection based on qualifiers

这看起来像

@Mapper
public interface MyEntityMapper {

    @Mapping(target = "someString", qualifiedByName = "myFancyMapping")
    MyEventPayload toEventPayload(MyEntity entity);

    @Named("myFancyMapping") // org.mapstruct.Named
    default String mapSomeString(String value) {
        return value + " custom mapping ";
    }
}

您还可以使用 Mapping#qualifiedBy 并构建您自己的 Qualifier (org.mapstruct.Qualifier) 注释。

这看起来像:

@Qualifier // org.mapstruct.Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface MyFancyMapping {
}

@Mapper
public interface MyEntityMapper {

    @Mapping(target = "someString", qualifiedBy = MyFancyMapping.class)
    MyEventPayload toEventPayload(MyEntity entity);

    @MyFancyMapping
    default String mapSomeString(String value) {
        return value + " custom mapping ";
    }
}

备选

另一种方法是在 @AfterMapping 中或使用表达式进行自定义映射(我不建议使用表达式,因为它容易出错)。