使用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
相关产品推荐
相关产品推荐

