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

使用Lombok @Mapper映射嵌套字段遇写入访问器错误,求解决方案

解决MapStruct映射多层级属性时的"Property has no write accessor"错误

错误信息

Property "delivery" has no write accessor in ClassA for target name "classBB_variable.delivery"

问题代码

@Mapper
@Mapping(target = "classBB_variable.customerId", source = "classA_variable.customerId")
@Mapping(target = "classBB_variable.delivery", source = "classA_variable.classAA_variable.delivery")
ClassB toCreateRequest(ClassA classA_variable);

@Value
@Builder(toBuilder = true)
public class ClassA {    
    private UUID customerId;
    private ClassAA classAA_variable;
}

@Data
@Builder
public class ClassAA {    
    private String delivery;
}

@Data
@Builder
public class ClassB {
    private ClassBB classBB_variable;
}

@Data
@Builder
public class ClassBB {
    private UUID customerId;
    private String delivery;
}

原因分析

这个错误的核心不是源对象的多层级属性读取问题,而是目标对象的嵌套实例未初始化:

  • MapStruct默认不会自动创建目标对象中嵌套的classBB_variable实例,当它为null时,无法对其delivery属性进行赋值;
  • 同时,ClassB和ClassBB使用了@Builder注解,旧版MapStruct对Builder模式下的嵌套对象支持不够完善,导致无法正确生成属性写入逻辑。

解决方法

方法1:让MapStruct自动处理嵌套对象的Builder

更新MapStruct到1.5.x及以上版本,并在Mapper注解中配置组件模型,同时显式定义嵌套对象的映射逻辑:

@Mapper(componentModel = "spring") // 根据项目环境选择,比如"default"或"spring"
public interface YourMapper {
    @Mapping(target = "classBB_variable.customerId", source = "classA_variable.customerId")
    @Mapping(target = "classBB_variable.delivery", source = "classA_variable.classAA_variable.delivery")
    ClassB toCreateRequest(ClassA classA_variable);

    // 显式定义ClassBB的映射规则,让MapStruct知道如何构建实例
    ClassBB mapToClassBB(UUID customerId, String delivery);
}

MapStruct会自动利用ClassBB的Builder创建实例并完成属性赋值。

方法2:初始化目标对象的嵌套实例

在ClassB的Builder中默认初始化classBB_variable,确保MapStruct赋值时它不为null:

@Data
@Builder
public class ClassB {
    private ClassBB classBB_variable;

    // 自定义Builder,默认初始化嵌套对象
    public static class ClassBBuilder {
        private ClassBB classBB_variable = ClassBB.builder().build();
    }
}

这样MapStruct在映射时直接对已存在的classBB_variable实例赋值即可。

方法3:使用@Mapping的expression手动构建嵌套对象

如果上述方法不适用,可以通过expression直接调用Builder创建实例:

@Mapper
public interface YourMapper {
    @Mapping(target = "classBB_variable", expression = "java(ClassBB.builder().customerId(classA_variable.getCustomerId()).delivery(classA_variable.getClassAA_variable().getDelivery()).build())")
    ClassB toCreateRequest(ClassA classA_variable);
}

这种方式更直接,绕过MapStruct的自动映射逻辑,手动控制嵌套对象的构建。


内容的提问来源于stack exchange,提问作者Akinn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 09:35:21