Mapstruct多源映射报错:目标类型无anotherObj读取访问器排查
MapStruct映射报错:No read accessor found for property anotherObj的解决办法
问题场景
我尝试用MapStruct实现Source与Target对象的映射,相关实体类代码如下:
@Data @Builder @Getter public class Source { public String str3; } @Data @Builder @Getter public class Target { public String str1; public String str2; public AnotherObj anotherObj; } @Data @Builder @Getter public class AnotherObj { public String str3; public String str4; }
编写的映射器代码:
@Mapping(target = "anotherObj", source = "request", qualifiedByName = "mapAnotherObjToSource") @Mapping(target = "anotherObj.str4", source = "str4") Target convert(Source request, String str4);
运行时出现错误:Java: No read accessor found for property anotherObj in target type.,我已经定义了Getter方法,尝试用@AfterMapping处理仍有问题:
@AfterMapping default void handleStr4(@MappingTarget Target target, Source source, String str4) { if (target.getAnotherObj() != null) { target.getCardMetadataInfo().setStr4(str4); } }
错误原因分析
- 注解冗余冲突:实体类同时使用
@Data和@Getter,@Data已包含@Getter、@Setter等注解,重复注解可能导致MapStruct对访问器的识别异常。 - 映射逻辑冲突:在映射器中同时指定了
anotherObj的整体映射和其属性anotherObj.str4的单独映射,MapStruct处理嵌套映射时逻辑冲突,无法正确识别访问器。 - @AfterMapping笔误:代码中调用了不存在的
getCardMetadataInfo()方法,应为getAnotherObj()。 - Builder模式影响:
@Builder生成的实例默认通过Builder创建,可能导致MapStruct无法正确使用@Data生成的Setter方法操作嵌套对象。
解决方案
1. 清理冗余注解
去掉实体类中重复的@Getter,保留@Data和@Builder即可:
@Data @Builder public class Source { public String str3; } @Data @Builder public class Target { public String str1; public String str2; public AnotherObj anotherObj; } @Data @Builder public class AnotherObj { public String str3; public String str4; }
2. 实现缺失的映射方法
确保mapAnotherObjToSource方法已正确定义,用于将Source转换为AnotherObj:
@Named("mapAnotherObjToSource") default AnotherObj mapAnotherObjToSource(Source source) { return AnotherObj.builder() .str3(source.getStr3()) .build(); }
3. 调整映射器配置(二选一)
方案一:用@AfterMapping处理嵌套属性赋值
去掉冲突的anotherObj.str4映射,通过@AfterMapping正确赋值:
@Mapping(target = "anotherObj", source = "request", qualifiedByName = "mapAnotherObjToSource") Target convert(Source request, String str4); @AfterMapping default void handleStr4(@MappingTarget Target target, String str4) { if (target.getAnotherObj() != null) { target.getAnotherObj().setStr4(str4); } }
方案二:在嵌套映射方法中直接传入str4
修改映射逻辑,在转换AnotherObj时直接使用str4参数,避免冲突:
@Mapping(target = "anotherObj", source = ".", qualifiedByName = "mapAnotherObjToSource") Target convert(Source request, @Context String str4); @Named("mapAnotherObjToSource") default AnotherObj mapAnotherObjToSource(Source source, @Context String str4) { return AnotherObj.builder() .str3(source.getStr3()) .str4(str4) .build(); }
4. 确保MapStruct配置正确
检查maven/gradle的注解处理器配置,确保MapStruct能正常生成映射实现类,例如maven配置:
<dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.5.5.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.5.5.Final</version> <scope>provided</scope> </dependency>
内容的提问来源于stack exchange,提问作者Pavanraotk
相关产品推荐
相关产品推荐

