MapStruct自定义int转String映射函数被全局应用的问题咨询
问题描述
我定义了一个将int类型映射为String类型的自定义映射函数,希望仅在特定场景下使用该函数,但它却被应用到了所有类型为int的源字段,而非仅标注了java(...)的字段。
源类代码
class Source { private int a; private int b; // getters etc... }
目标类代码
class Target { private String a; private String b; // getters etc... }
映射器代码
@Mapping(source="a", target="a") // 本以为没必要,只是为了更明确 @Mapping(target="b", expression = "java(modify(b))") public abstract Target sourceToTarget(Source source); String modify(int value) { return "prefix_" + value; }
期望生成的代码逻辑
target.setA(String.valueOf(a)); target.setB(modify(b));
实际生成的代码逻辑
target.setA(modify(a)); target.setB(modify(b));
移除expression注解和modify函数后,MapStruct会对两个字段都使用String.valueOf进行转换。已尝试MapStruct 1.4.2.FINAL和1.5.2.FINAL版本,相关类使用了Lombok,但此前未出现问题。
请问该行为是否符合预期?若符合,该如何实现我想要的效果?
解答
行为是否符合预期?
符合预期。MapStruct会自动扫描映射器中定义的类型转换方法,只要方法的参数类型和返回类型匹配当前需要转换的源-目标类型对(此处为int→String),就会将其作为全局默认转换方法使用,不受expression注解的限制。你定义的modify(int value)正好匹配int到String的转换规则,因此会被自动应用到所有符合该类型对的字段映射中。
实现预期效果的方案
有两种可靠的实现方式:
将自定义转换方法封装到独立转换器类,按需指定使用
首先创建独立的转换器类,并给目标方法添加@Named注解标记:import org.mapstruct.Named; public class CustomIntConverter { @Named("addPrefix") public String modify(int value) { return "prefix_" + value; } }然后在映射器中,通过
qualifiedByName指定仅字段b使用该自定义转换,同时通过@Mapper(uses = ...)引入转换器类:import org.mapstruct.Mapper; import org.mapstruct.Mapping; @Mapper(uses = CustomIntConverter.class) public abstract class SourceTargetMapper { @Mapping(source = "a", target = "a") // 自动使用默认int→String转换 @Mapping(source = "b", target = "b", qualifiedByName = "addPrefix") public abstract Target sourceToTarget(Source source); }在映射器中显式定义默认转换方法
在映射器内添加默认的int→String转换方法,MapStruct会优先使用这个默认方法处理未指定自定义转换的字段,仅在你通过expression或qualifiedByName指定时才调用modify方法:@Mapping(target="b", expression = "java(modify(b))") public abstract Target sourceToTarget(Source source); // 显式定义默认int转String的方法 default String intToString(int value) { return String.valueOf(value); } String modify(int value) { return "prefix_" + value; }
内容的提问来源于stack exchange,提问作者ceran

