如何使用MapStruct处理双向关联的对象转换
解决MapStruct双向关联属性未设置的问题
针对你遇到的Car与CarUser双向转换时,CarUser的car属性未自动关联的问题,有两种简洁的解决方案,核心思路都是在转换流程中补全双向关联逻辑:
方案一:使用@AfterMapping后置处理(推荐)
MapStruct提供的@AfterMapping注解可以在对象转换完成后执行自定义逻辑,正好用来调用linkUser方法建立双向关联。修改你的CarConverter如下:
@Mapper(uses = UserConverter.class) public interface CarConverter { Car convert(final CarDTO car); CarDTO convert(final Car car); // CarDTO转Car后,补全CarUser与Car的双向关联 @AfterMapping default void setupCarUserLinks(CarDTO source, @MappingTarget Car target) { target.getUsers().forEach(target::linkUser); } // Car转CarDTO后,补全CarUserDTO与CarDTO的双向关联 @AfterMapping default void setupCarUserDTOLinks(Car source, @MappingTarget CarDTO target) { target.getUsers().forEach(target::linkUser); } }
原理说明:
- MapStruct会先自动完成所有属性的映射,包括Car的users列表(通过UserConverter转换每个CarUserDTO到CarUser)
- 转换完成后触发
@AfterMapping标注的方法,此时target已经是完整的Car/CarDTO实例 - 调用
target.linkUser(user),既保证user被加入users列表(重复调用不影响业务逻辑),同时自动设置user的car属性为当前target
方案二:重载转换方法,传递关联实例
通过给UserConverter添加带上下文参数的重载方法,在转换CarUser时直接传入对应的Car实例:
第一步:修改UserConverter
@Mapper public interface UserConverter { // 基础转换方法 CarUser convert(final CarUserDTO user); CarUserDTO convert(final CarUser user); // 带Car关联的转换方法 @Mapping(target = "car", source = "car") CarUser convert(CarUserDTO userDTO, Car car); // 带CarDTO关联的转换方法 @Mapping(target = "car", source = "carDTO") CarUserDTO convert(CarUser user, CarDTO carDTO); }
第二步:修改CarConverter,调用重载方法
@Mapper(uses = UserConverter.class) public interface CarConverter { @Mapping(target = "users", expression = "java( source.getUsers().stream().map(userDTO -> userConverter.convert(userDTO, target)).collect(java.util.stream.Collectors.toList()) )") Car convert(final CarDTO car); @Mapping(target = "users", expression = "java( source.getUsers().stream().map(user -> userConverter.convert(user, target)).collect(java.util.stream.Collectors.toList()) )") CarDTO convert(final Car car); }
原理说明:
利用MapStruct的expression属性手动处理users列表的转换,将正在构建的target(即转换后的Car/CarDTO)作为参数传给UserConverter的重载方法,直接给CarUser/CarUserDTO设置car属性。
两种方案都能解决你的问题,方案一更简洁易维护,推荐使用。
内容的提问来源于stack exchange,提问作者j3d
相关产品推荐
相关产品推荐

