You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 18:34:52