Mapstruct如何使用MappingControl禁用多余自动映射解决字段误映射问题
MapStruct自定义String转换方法不自动应用到其他字段的解决方案
你遇到的问题是MapStruct会把Mapper中定义的所有同类型参数返回的方法当成全局类型转换器,自动匹配到所有对应类型的字段映射上,下面给出两种可直接落地的方案:
方案1:使用@Named限定方法(更推荐新手使用)
这个方案不需要额外自定义注解,仅需给自定义转换方法加名称限定,只有显式指定时才会调用,完全不会影响其他同类型字段映射:
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Named; import org.mapstruct.factory.Mappers; @Mapper public interface CustomerMapper { CustomerMapper INSTANCE = Mappers.getMapper(CustomerMapper.class); // customerName字段会直接映射,不会调用自定义转换方法 @Mapping(source = "customerName", target = "name") // 显式指定id字段使用名称为magicIdGenerator的方法做转换 @Mapping(source = "id", target = "magicid", qualifiedByName = "magicIdGenerator") Customer toCustomer(CustomerDto customerDto); // 加@Named注解后,该方法不会被当成全局String转换器自动调用 @Named("magicIdGenerator") default String getMagicId(String id) { // 你的业务逻辑 return "magic_" + id; } }
方案2:使用MappingControl控制方法适用范围
如果你需要更精细的全局映射控制,可以用这个方案:
- 首先自定义映射控制注解:
import org.mapstruct.control.MappingControl; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.CLASS) // 禁用该方法被自动应用到同类型的隐式转换 @MappingControl(disable = MappingControl.Use.MAPPING_METHOD) public @interface DisableAutoMapping { }
- 将注解加到自定义转换方法上即可:
@Mapper public interface CustomerMapper { CustomerMapper INSTANCE = Mappers.getMapper(CustomerMapper.class); @Mapping(source = "customerName", target = "name") @Mapping(target= "magicid", expression="java(getMagicId(customerDto.getId()))") Customer toCustomer(CustomerDto customerDto); // 加自定义控制注解 @DisableAutoMapping default String getMagicId(String id) { // 你的业务逻辑 return "magic_" + id; } }
其他可选方案
以上两种不是唯一的解决方法,还有其他实现方式:
- 将自定义转换方法放到单独的工具类中,不在当前Mapper里定义,仅在需要时通过表达式显式调用
- 给不需要应用转换的字段显式指定
qualifiedByName,配置默认的直接转换规则
新手注意事项
@Mapping注解中target、source的属性值需要和对应类的字段名完全一致,注意大小写,你原代码中的Customer类字段是magicid,不是magicId- 字符串类型的配置值需要加引号,原代码中
target= magicId的写法会直接编译报错
内容的提问来源于stack exchange,提问作者0c7
相关产品推荐
相关产品推荐

