当前位置:主页 > 软件编程 > JAVA代码 >

MapStruct表达式应用及避坑详解

时间:2023-03-08 12:02:45 | 栏目:JAVA代码 | 点击:

前言

生成的映射代码使用简单的方法调用,因此速度快,类型安全且易于理解。MapStruct的表达式功能是为了处理特殊对象属性的映射问题,比如DTO中的status属性转换成PO中的status需要进一步的处理,这个时候就需要用到表达式功能了。这里不再赘述关于MapStruct的使用问题,更多的使用教程可参考文档

MapStruct官方文档:https://mapstruct.org/documentation/stable/reference/html/#mapping-composition

遇到的问题

先看一段映射的代码:

@Mapper(imports = CustomProcessors.class)
public interface DepartmentsMapper {
    @Mapping(target = "status", expression = "java( DepartmentsMapper.toStatus(department.getStatus()) )")
    DepartmentsVO boToVo(DepartmentBO department);
    static String toStatus(String status){
        return status + "状态";
    }
}

原本这段代码表达的语义是:将DepartmentBO的status属性赋值给DepartmentsVO时,需要进行一些简单的转换,转换的方法就是Mapper接口里定义的toStatus静态方法。可最终MapStruct生成的代码把其他属性的赋值动作也做了处理。生成的代码如下:

可以看到除了指定的status属性加上了表达式中的代码,其他的属性也都加上了,这不是我们想要的效果。

发现原因

楼主反复查看官方文档,最后就差把源码拉下来看实现逻辑了,最后一个闪念猜想到了可能的原因。上面关于表达式的使用代码没有问题,官方文档也写的很清楚。主要是因为这里触发了MapStruct的一个隐藏功能:仔细观察生成的代码发现,只有Integer属性的字段加上表达式中的代码了,楼主推断只要在定义maping的接口中定义了转换方法就会被自动应用到相同类型属性的转换上。后面验证确实如此,比如我去掉表达式的定义:

@Mapper(imports = CustomProcessors.class)
public interface DepartmentsMapper {
    DepartmentsVO boToVo(DepartmentBO department);
    static Integer toStatus(Integer status){
        return status + 1;
    }
}

最终生成的代码还是所有的Integer属性的值都加上了toStatus的处理了

结语

最后发现的这个特性竟然在官方文档上找不到丝毫的描述,其实可以算一个非常不错的功能,可以统一处理相同类型的属性,比如属性是一个对象时,只是在博主的这个场景下使用不到。最后的解决方案是将表达式中的代码定义从Mapper接口中移出去就好了。

您可能感兴趣的文章:

相关文章