为什么@Builder 注解默认父类字段不可见

CustomerCondition customerCondition = new CustomerCondition();

customerCondition.setId(condition.getCustomerId());

customerCondition.setKeyword(condition.getCustomerKeyword());

customerCondition.setPageNum(1);

customerCondition.setPageSize(Integer.MAX_VALUE);

List<CustomerResponse> customerResponseList = customerService.getPage(

CustomerCondition.defaultBuilder()

.id(condition.getCustomerId())

.keyword(condition.getCustomerKeyword())

.build()

).getRecords();

为什么build注解设置父类字段的值,会爆红

根据你提供的代码,问题在于 CustomerCondition.defaultBuilder() 创建的构建器可能没有包含父类 PageRequest 的字段。这是 Lombok @Builder 注解的一个常见限制。

问题分析

  1. 父类字段不可见 :Lombok 的 @Builder 默认只处理当前类中声明的字段,不包含父类字段

  2. 构建器方法缺失defaultBuilder() 返回的构建器可能没有父类的 pageNumpageSize 等方法

解决方案

方案一:使用 @SuperBuilder(推荐)

这是 Lombok 专门用于处理继承关系的构建器注解。

修改 PageRequest 类:

java

复制代码
package com.admin.common;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;

@Getter
@Setter
@SuperBuilder  // 添加这个注解
public class PageRequest {
    private Integer pageNum = 1;
    private Integer pageSize = 20;
    private String keyword;
    // ... 其他字段
}

修改 CustomerCondition 类:

java

复制代码
package com.admin.condition;

import com.admin.common.PageRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import java.io.Serializable;
import java.util.List;

@Data
@Schema(description = "客户表")
@SuperBuilder(toBuilder = true)  // 将 @Builder 改为 @SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class CustomerCondition extends PageRequest implements Serializable {

    private static final long serialVersionUID = 1L;

    @Schema(description = "客户id")
    private Long id;
    
    @Schema(description = "主键列表")
    private List<Long> ids;

    @Schema(description = "客户状态")
    private String customerStatus;

    @Schema(description = "是否查询客户账户")
    private Boolean isQueryAccount = false;

    @Schema(description = "客户账户条件")
    private CustomerAccountCondition accountCondition;
    
    // 删除之前的 defaultBuilder() 方法,使用 @SuperBuilder 提供的构建器
}

使用方式:

java

复制代码
List<CustomerResponse> customerResponseList = customerService.getPage(
    CustomerCondition.builder()  // 直接使用 @SuperBuilder 生成的构建器
        .pageNum(1)
        .pageSize(Integer.MAX_VALUE)
        .id(condition.getCustomerId())
        .keyword(condition.getCustomerKeyword())
        .build()
).getRecords();

方案二:手动添加父类字段到构建器(如果无法使用 @SuperBuilder)

修改 CustomerCondition 类:

java

复制代码
@Data
@Schema(description = "客户表")
@Builder(builderClassName = "CustomerConditionBuilder", builderMethodName = "hiddenBuilder")
@AllArgsConstructor
@NoArgsConstructor
public class CustomerCondition extends PageRequest implements Serializable {
    
    // ... 字段定义
    
    // 自定义构建器类
    public static class CustomerConditionBuilder {
        // 添加父类字段
        private Integer pageNum = 1;
        private Integer pageSize = 20;
        private String keyword;
        // 其他父类字段...
        
        // 添加父类字段的设置方法
        public CustomerConditionBuilder pageNum(Integer pageNum) {
            this.pageNum = pageNum;
            return this;
        }
        
        public CustomerConditionBuilder pageSize(Integer pageSize) {
            this.pageSize = pageSize;
            return this;
        }
        
        public CustomerConditionBuilder keyword(String keyword) {
            this.keyword = keyword;
            return this;
        }
        
        // 修改 build 方法以包含父类字段
        public CustomerCondition build() {
            CustomerCondition condition = new CustomerCondition();
            // 设置父类字段
            condition.setPageNum(this.pageNum);
            condition.setPageSize(this.pageSize);
            condition.setKeyword(this.keyword);
            // 设置当前类字段
            condition.setId(this.id);
            condition.setIds(this.ids);
            condition.setContractArea(this.contractArea);
            condition.setCustomerCategory(this.customerCategory);
            condition.setCustomerStatus(this.customerStatus);
            condition.setIsQueryAccount(this.isQueryAccount);
            condition.setAccountCondition(this.accountCondition);
            return condition;
        }
    }
    
    // 提供公共的构建器方法
    public static CustomerConditionBuilder builder() {
        return new CustomerConditionBuilder();
    }
}

方案三:使用组合代替继承

如果父类字段不多,可以考虑使用组合:

java

复制代码
@Data
@Schema(description = "客户表")
@Builder(toBuilder = true)
@AllArgsConstructor
@NoArgsConstructor
public class CustomerCondition implements Serializable {

    private static final long serialVersionUID = 1L;

    // 包含 PageRequest 的字段
    @Schema(description = "页码")
    @Builder.Default
    private Integer pageNum = 1;
    
    @Schema(description = "每页条数")
    @Builder.Default
    private Integer pageSize = 20;
    
    @Schema(description = "关键词")
    private String keyword;
    
    // 原有的字段
    @Schema(description = "客户id")
    private Long id;
    
    @Schema(description = "主键列表")
    private List<Long> ids;
    
    // ... 其他字段
}

方案四:简化代码,不使用构建器

既然你之前的代码可以工作,可以直接使用:

java

复制代码
CustomerCondition customerCondition = new CustomerCondition();
customerCondition.setId(condition.getCustomerId());
customerCondition.setKeyword(condition.getCustomerKeyword());
customerCondition.setPageNum(1);
customerCondition.setPageSize(Integer.MAX_VALUE);

List<CustomerResponse> customerResponseList = customerService.getPage(customerCondition).getRecords();

或者在类中添加一个便捷方法:

java

复制代码
// 在 CustomerCondition 类中添加
public static CustomerCondition createDefault() {
    CustomerCondition condition = new CustomerCondition();
    condition.setPageNum(1);
    condition.setPageSize(20);
    condition.setIsQueryAccount(false);
    return condition;
}

// 使用方式
CustomerCondition customerCondition = CustomerCondition.createDefault();
customerCondition.setId(condition.getCustomerId());
customerCondition.setKeyword(condition.getCustomerKeyword());
customerCondition.setPageSize(Integer.MAX_VALUE);

推荐方案

  1. 首选方案一 (使用 @SuperBuilder):

    • 最符合 Lombok 的设计理念

    • 代码最简洁

    • 完全支持继承

  2. 如果无法升级 Lombok 版本(需要 1.18.2+):

    • 使用方案四,保持简单

    • 或者使用方案二的变体

注意事项

  1. Lombok 版本要求@SuperBuilder 需要 Lombok 1.18.2 或更高版本

  2. 依赖更新 :确保所有相关类都正确导入 @SuperBuilder

  3. 编译插件 :确保 IDE 的 Lombok 插件已更新到支持 @SuperBuilder 的版本

选择适合你项目情况的方案。如果项目 Lombok 版本较低且无法升级,建议使用方案四(简化代码)。如果可以升级 Lombok,强烈推荐使用方案一。

相关推荐
zfoo-framework4 分钟前
帧同步和状态同步
java
charlotte102410247 分钟前
高并发:关于在等待学校教务系统选课时的碎碎念
java·运维·网络
亓才孓12 分钟前
[JDBC]PreparedStatement替代Statement
java·数据库
_F_y34 分钟前
C++重点知识总结
java·jvm·c++
打工的小王35 分钟前
Spring Boot(三)Spring Boot整合SpringMVC
java·spring boot·后端
毕设源码-赖学姐37 分钟前
【开题答辩全过程】以 高校体育场馆管理系统为例,包含答辩的问题和答案
java·spring boot
我真会写代码38 分钟前
SSM(指南一)---Maven项目管理从入门到精通|高质量实操指南
java·spring·tomcat·maven·ssm
vx_Biye_Design39 分钟前
【关注可免费领取源码】房屋出租系统的设计与实现--毕设附源码40805
java·spring boot·spring·spring cloud·servlet·eclipse·课程设计
DN金猿44 分钟前
接口路径正确,请求接口却提示404
java·tomcat
Maynor9961 小时前
OpenClaw 玩家必备:用 AI 自动追踪社区最新动态
java·服务器·人工智能