Mapstruct映射双向OneToMany/ManyToOne关系返回全空字段问题
问题解决方案
问题根因
- 双向关联触发无限递归映射:Policy与User的实体和DTO都存在双向引用,Mapstruct默认会递归执行映射逻辑,要么触发栈溢出,要么生成的映射实现类逻辑异常,导致所有字段映射结果为空
- Mapper未配置嵌套映射依赖:PolicyMapper没有关联UserMapper,Mapstruct无法正确识别嵌套的User类型字段映射规则
- 注解处理器执行顺序错误:Lombok和Mapstruct的注解处理器执行顺序不对,Mapstruct生成映射代码时无法读取Lombok生成的Getter/Setter方法,导致字段赋值失败
- 多null值的关联字段没有适配策略:大量Policy的user字段为null,没有对应null值映射策略时可能触发映射异常
解决方案
步骤1:打断循环映射链路(二选一即可)
方案A:精简不必要的关联字段(推荐)
如果业务不需要在UserDTO中返回关联的Policy列表,直接删除UserDTO中的public List<PolicyDTO> policyList字段,从根源避免循环映射。
方案B:忽略循环关联字段
如果必须保留该字段,在映射规则中忽略循环引用的字段:
@Mapper(componentModel = "spring") public interface UserMapper { // 忽略policyList字段避免循环映射 @Mapping(target = "policyList", ignore = true) UserDTO toUserDTO(User user); List<UserDTO> toUserListDTO(List<User> UsersList); }
步骤2:配置Mapper嵌套映射依赖
在PolicyMapper中指定使用UserMapper处理嵌套的User字段映射:
@Mapper (componentModel = "spring", uses = UserMapper.class) public interface PolicyMapper { PolicyDTO policytoPolicyDTO(Policy policy); List<PolicyDTO> toPolicyListDTO(List<Policy> policies); }
步骤3:修正注解处理器配置
保证Lombok早于Mapstruct执行,并且引入lombok-mapstruct-binding适配包,Maven配置示例如下:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>11</source> <!-- 替换为你使用的JDK版本 --> <target>11</target> <annotationProcessorPaths> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.2.0</version> </path> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.4.2.Final</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>
步骤4:配置null值映射策略(可选)
添加null值映射规则,适配大量user字段为null的场景:
import org.mapstruct.NullValueMappingStrategy; @Mapper( componentModel = "spring", uses = UserMapper.class, nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL ) public interface PolicyMapper { // 原有方法不变 }
验证方式
修改完成后执行项目clean后重新编译,查看target/generated-sources/annotations目录下生成的PolicyMapperImpl实现类,确认字段映射逻辑正常,没有无限递归调用的代码即可。
内容的提问来源于stack exchange,提问作者nikos kor
相关产品推荐
相关产品推荐

