Lombok @Builder结合Mapstruct时覆盖类属性默认值问题求助
解决思路
1. 让MapStruct优先使用默认构造函数而非Builder
MapStruct默认会优先调用Lombok生成的Builder创建对象,这会覆盖字段的初始化默认值。可以通过全局或局部配置,强制MapStruct改用默认构造函数实例化对象,从而保留字段初始值:
- 局部配置(单Mapper生效):在目标Mapper接口上添加
@Mapper(builder = @Builder(disableBuilder = true)):
@Mapper(componentModel = "spring", builder = @Builder(disableBuilder = true)) public interface MyEntityMapper { MyEntity toEntity(MyDataTransferObject source); }
- 全局配置(所有Mapper生效):在项目根目录创建
mapstruct-config.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?> <mapstruct-config xmlns="http://mapstruct.org/configurations" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://mapstruct.org/configurations https://mapstruct.org/schemas/mapstruct-config-1.5.xsd"> <default-options> <builder disable-builder="true"/> </default-options> </mapstruct-config>
然后在Maven/Gradle的编译插件中指定该配置文件:
Maven示例:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <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.30</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.2.0</version> </path> </annotationProcessorPaths> <compilerArgs> <arg>-Amapstruct.config=${project.basedir}/mapstruct-config.xml</arg> </compilerArgs> </configuration> </plugin> </plugins> </build>
2. 批量处理@Builder.Default注解
如果必须保留Builder模式,可以通过工具批量添加注解,降低手动修改成本:
- IDE结构化搜索替换:以IntelliJ IDEA为例,使用Structural Search and Replace功能批量处理:
搜索模板:
@Column($ColumnAnnotation$) private $Type$ $FieldName$ = $DefaultValue$;
替换模板:
@Builder.Default @Column($ColumnAnnotation$) private $Type$ $FieldName$ = $DefaultValue$;
该方式可一次性匹配所有带初始化值的字段,批量添加@Builder.Default。
- 自定义注解简化配置:创建自定义注解,结合Lombok的
copyableAnnotations配置实现间接批量生效:
先定义自定义注解:
@Target(ElementType.FIELD) @Retention(RetentionPolicy.SOURCE) public @interface DefaultBuilderField { }
然后在项目根目录的lombok.config中添加:
lombok.copyableAnnotations += com.yourpackage.DefaultBuilderField lombok.builder.defaultIsAlwaysExplicit = true
后续只需给带默认值的字段添加@DefaultBuilderField,Lombok会自动识别并应用Builder默认值逻辑。
3. 自定义MapStruct对象创建工厂
实现MapStruct的ObjectFactory接口,自定义对象实例化逻辑,确保保留字段初始化值:
@Component public class DefaultValueObjectFactory implements ObjectFactory { @Override public <T> T create(Class<T> type) { try { // 通过默认构造函数创建实例,保留字段初始值 return type.getDeclaredConstructor().newInstance(); } catch (Exception e) { throw new RuntimeException("Failed to create instance of " + type.getName(), e); } } }
然后在Mapper接口中指定该工厂:
@Mapper(componentModel = "spring", objectFactory = DefaultValueObjectFactory.class) public interface MyEntityMapper { MyEntity toEntity(MyDataTransferObject source); }
内容的提问来源于stack exchange,提问作者naumb
相关产品推荐
相关产品推荐

