如何结合Lombok toBuilder与MapStruct实现不可变Bean更新?
问题描述
现有使用Lombok注解的两个类:
@Getter @NoArgsConstructor @AllArgsConstructor @Builder(toBuilder = true) public class ClassA { private String id; private String a; private String b; } public class ClassB { private String b; }
需要实现一个更新ClassA实例的映射方法,定义如下:
ClassA update(ClassB b, @MappingTarget ClassA a);
但MapStruct生成的代码未执行字段赋值(因ClassA无setter),生成代码如下:
@Override public ClassA update(ClassB b, ClassA a) { if ( b == null ) { return a; } return a; }
尝试使用@BeanMapping(builder = @Builder(buildMethod = "toBuilder"))无效,期望生成如下代码:
public ClassA update(ClassB b, ClassA a) { if ( b == null ) { return a; } ClassA.ClassABuilder builder = a.toBuilder(); builder.b(b.getB()); return builder.build(); }
如何实现该需求?
解决方案
关键配置步骤
- 添加Lombok-MapStruct绑定依赖
MapStruct无法直接识别Lombok生成的toBuilder方法,必须引入lombok-mapstruct-binding包打通两者的注解处理流程。如果使用Maven,在pom.xml的annotationProcessorPaths中添加:
<path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.2.0</version> </path>
完整Maven编译插件配置示例:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.5.5.Final</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.26</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.2.0</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>
- 修正Mapper方法的注解配置
之前使用的buildMethod参数错误,需改用builderMethod指定从已有实例获取Builder的方法toBuilder,同时在Mapper接口上添加@Mapper注解:
@Mapper(componentModel = "spring") // 可根据项目需求选择componentModel,如"cdi"或默认 public interface ClassMapper { @BeanMapping(builder = @Builder(builderMethod = "toBuilder")) ClassA update(ClassB b, @MappingTarget ClassA a); }
- 确保版本兼容性
使用MapStruct 1.4.0及以上版本、Lombok 1.18.16及以上版本,避免因版本过低导致的注解识别问题。
效果验证
配置完成后,MapStruct会生成符合预期的代码:通过a.toBuilder()创建Builder实例,更新对应字段后生成新的ClassA对象返回。
内容的提问来源于stack exchange,提问作者Wafa
相关产品推荐
相关产品推荐

