Kotlin中MapStruct@AfterMapping报错:仅可应用于已实现类
Kotlin中MapStruct @AfterMapping 编译报错解决
问题场景
在Kotlin结合Spring Boot使用MapStruct进行对象映射时,需在映射完成后通过@AfterMapping调用Spring Repository和Service获取关联对象,但执行kaptKotlin任务时编译失败。
原代码
@Mapper(componentModel = "spring") interface ObjectMapper { @Mappings( Mapping(source = "aCode", target = "a.code"), Mapping(source = "bCode", target = "b.code") ) fun convertFormDtoToEntity( dto: ObjectFormDto, @Context aRepo: ARepository, @Context bService: BService ): Object @AfterMapping fun afterMappingFormDtoToEntity( dto: ObjectFormDto, @Context aRepo: ARepository, @Context bService: BService, @MappingTarget entity: Object ) { entity.a = aRepo.findByA(entity.a.code) entity.b = bService.getB(entity.b.code) } }
报错信息
error: @AfterMapping can only be applied to an implemented class public abstract void afterMappingFormDtoToEntity(@org.jetbrains.annotations.NotNull()...
解决方案
方案1:将Mapper改为抽象类
MapStruct允许使用抽象类作为Mapper载体,抽象类中的方法可直接实现,不会触发该错误:
@Mapper(componentModel = "spring") abstract class ObjectMapper { @Mappings( Mapping(source = "aCode", target = "a.code"), Mapping(source = "bCode", target = "b.code") ) abstract fun convertFormDtoToEntity( dto: ObjectFormDto, @Context aRepo: ARepository, @Context bService: BService ): Object @AfterMapping fun afterMappingFormDtoToEntity( dto: ObjectFormDto, @Context aRepo: ARepository, @Context bService: BService, @MappingTarget entity: Object ) { entity.a = aRepo.findByA(entity.a.code) entity.b = bService.getB(entity.b.code) } }
方案2:为接口中的@AfterMapping方法添加@JvmDefault注解
若坚持使用接口,需让Kotlin生成Java兼容的默认方法,添加@JvmDefault注解并开启对应配置:
- 修改Mapper接口:
@Mapper(componentModel = "spring") interface ObjectMapper { @Mappings( Mapping(source = "aCode", target = "a.code"), Mapping(source = "bCode", target = "b.code") ) fun convertFormDtoToEntity( dto: ObjectFormDto, @Context aRepo: ARepository, @Context bService: BService ): Object @JvmDefault @AfterMapping fun afterMappingFormDtoToEntity( dto: ObjectFormDto, @Context aRepo: ARepository, @Context bService: BService, @MappingTarget entity: Object ) { entity.a = aRepo.findByA(entity.a.code) entity.b = bService.getB(entity.b.code) } }
- 在
build.gradle.kts的kotlin配置中开启默认方法支持:
kotlin { sourceSets.all { languageSettings { optIn("kotlin.jvm.JvmDefault") } } }
当前环境配置
MapStruct版本:1.5.2.Final,kapt版本:1.6.10,kapt配置如下:
kapt { arguments { arg("mapstruct.unmappedTargetPolicy", "IGNORE") } keepJavacAnnotationProcessors = true }
内容的提问来源于stack exchange,提问作者3LexW
相关产品推荐
相关产品推荐

