mapsturct 避坑指南

330 阅读2分钟

mapsturct各种情况使用

1、常用注解

@Mapper(componentModel = "spring",nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE),builder = @Builder(disableBuilder = true)
参数作用
componentModelcomponentModel="spring"必加 将这个实现类Spring 容器来管理,不然需要手动实现 否则报错 A component required a bean of type 'com.xxx.xxx' that could not be found
nullValuePropertyMappingStrategy定空值属性映射策略 这里 NullValuePropertyMappingStrategy.IGNORE 表示 直接忽略不转换
builder = @Builder(disableBuilder = true)注解用于禁用构建器方法的生成,确保使用传统的构造函数进行对象创建。

2、基本使用

目标实体类与源实体类 参数类型参数名相同时 xxx<实体类> 或者 直接 实体类 都可以

@Mapper(componentModel = "spring",nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)public interface UserConvert {
   
    /**
     * user inToOut
     * NullValuePropertyMappingStrategy.IGNORE 当参数未null时候不转换
     * @param userInput
     * @return
     */
    UserOutput userConvert(UserInput userInput);
}

3、目标与源实体类属性名不一致

问题解决方法
实体类直接使用 @Mapping注解target为目标参数名(左) source为源参数名(右)
xxx<实体类>先写xxx<实体类> convert(xxx<实体类> xxx) 然后再将写一个 转换 出参为目标转换中泛型 入参为源目标泛型 之后将注解加载这里 之后就跟↑一样。
​
    List<AggOutRepairOrderLabourTwoBO> labourAggOutBoToAggOutBo(List<RepairOrderLabourSumAggOutBO> list);
​
    @Mapping(target = "repairName",source = "srvName")
    @Mapping(target = "jobName",source = "srvTypeName")
    @Mapping(target = "workshopTeam",source = "workByName")
    AggOutRepairOrderLabourTwoBO labourAggOutBoToAggOutBo(RepairOrderLabourSumAggOutBO list);

4、复杂转换情况

1、多个入参属性名与出参属性名不一致

参数expression在MapStruct中用于指定一个Java表达式的字符串。这个表达式可以在生成映射代码时被用来生成目标属性的值。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ComprehensiveInputVO {
    private MusicDTO music1;
    private List<UserInput> userInputList1;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ComprehensiveOutputVO {
    private MusicDTO music2;
    private List<UserInput> userInputList2;
}
  @Mapping(target = "music2", source = "music1")
  @Mapping(target = "userInputList2", source = "userInputList1")
  ComprehensiveOutputVO complexConvert(ComprehensiveInputVO comprehensiveInputVO);

2、多个入参属性名与出参属性名不一致,同时入参属性中的属性也不一致

首先如果是普通实体类 - 直接对应名字.属性 目标属性和源属性即可

    @Mapping(target = "music2.musicName",source = "music1.userMusicName")
    @Mapping(target = "music2.ranking",source = "music1.rank")
    @Mapping(target = "music2.mySinger",source = "music1.singer")
    @Mapping(target = "music2.mYLyricist",source = "music1.lyricist")
    @Mapping(target = "userInputList2",source = "userInputList1")
    ComprehensiveOutputVO complexConvert(ComprehensiveInputVO comprehensiveInputVO);

若还有其他复杂,如list<实体类> 这种不仅名字不一样,属性也有不一样,先使用 @Mapping(target = "userInputList2",source = "userInputList1") 让他能找到对应属性,然后 比如是list 再按照3的程序走一遍即可

 @Mapping(target = "password",source = "userPassword")
    @Mapping(target = "name",source = "userName")
    UserOutput userConvert(UserInput userInput);
​
    /**
     * userConvertList
     * @param inputList
     * @return
     */
    List<UserOutput> userConvertList(List<UserInput> inputList);
​
​
/*
* @Mapping(expression = "java(musicDTO1.getMusicName() + "10086")",target = "music1.musicName")
    ComprehensiveOutputVO complexConvert(ComprehensiveInputVO comprehensiveInputVO); 这样给属性赋值也行
*/

5、其他情况

处理逻辑,调用静态方法,自己手动写验证参数是否正确等等

 @Mapping(expression = "java(com.example.problems.bo.Constant.templatePost(musicDTO1.getMusicName()))", target = "music1.musicName")
    ComprehensiveOutputVO complexConvert(ComprehensiveInputVO comprehensiveInputVO);
public class Constant {
    private String name = "校长";

    public static String templatePost(String code) {
        if (StringUtils.isEmpty(code)) {
            return code;
        }
        switch (code) {
            case "123":
                return "SA";
            case "1234":
                return "CR";
            default:
                return "meiyou";
        }
    }
}
@Mapping(expression = "java(SuspendConvert.compareSize(bo))", target = "temp")
FactoryPageInBo toFactoryPageInBo(BffFactoryPageInBo bo);

 static Integer compareSize(BffFactoryPageInBo bo) {
    处理逻辑
    }