You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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注解并开启对应配置:

  1. 修改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)
    }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 06:24:46