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

Lombok @Builder多构造器继承场景下字段初始化失败问题

Lombok @Builder 继承场景下部分字段初始化失败问题

问题说明

抽象父类EventDTO被CreateTaskLogDTO继承,两者各定义了两个构造器,子类构造器分别调用父类对应的构造器。其中标注@Builder(builderMethodName = "buildWithSpecificParamsNoID")的构造器工作正常,但标注@Builder(builderMethodName = "buildWithOperationStringID")的构造器无法初始化Long id和String operationString字段。测试验证发现:

  • 使用buildWithOperationStringID构建对象时,id和operationString字段未被正确设置,其余字段正常
  • 使用buildWithSpecificParamsNoID构建对象时,所有字段均可正常初始化

父类 EventDTO 源码

package com.wwme.wwme.log.domain.DTO;

import com.wwme.wwme.group.domain.Group;
import com.wwme.wwme.log.domain.OperationType;
import com.wwme.wwme.task.domain.Task;
import com.wwme.wwme.user.domain.User;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;

@Getter
@Setter
public abstract class EventDTO {

    public EventDTO(Long id, User user, Group group, OperationType operationTypeEnum, LocalDateTime operationTime, String operationString, Task task) {
        this.id = id;
        this.user = user;
        this.group = group;
        this.operationTypeEnum = operationTypeEnum;
        this.operationTime = operationTime;
        this.operationString = operationString;
        this.task = task;
    }

    public EventDTO(User user, Group group, OperationType operationTypeEnum, LocalDateTime operationTime, Task task) {
        this.user = user;
        this.group = group;
        this.operationTypeEnum = operationTypeEnum;
        this.operationTime = operationTime;
        this.task = task;
    }

    protected Long id;
    protected User user;
    protected Group group;
    protected Task task;
    protected OperationType operationTypeEnum;
    protected LocalDateTime operationTime;
    protected String operationString;


    //Calculate Operation String based on given parameters
    public abstract void setOperationStr();

    @Override
    public String toString() {
        return "EventDTO{" +
                "id=" + id +
                ", user=" + user.getNickname() +
                ", group=" + group.getGroupName() +
                ", task=" + task.getTaskName() +
                ", operationTypeEnum=" + operationTypeEnum +
                ", operationTime=" + operationTime +
                ", operationString='" + operationString + '\'' +
                '}';
    }
    //set specific fields for 
    public abstract void setSpecificFields();
    public abstract String convertToString();
}

子类 CreateTaskLogDTO 源码

package com.wwme.wwme.log.domain.DTO;

import com.wwme.wwme.group.domain.Group;
import com.wwme.wwme.log.domain.OperationType;
import com.wwme.wwme.task.domain.Task;
import com.wwme.wwme.user.domain.User;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;

@Slf4j
@Getter
public class CreateTaskLogDTO extends EventDTO{
    private String newTaskName;

    @Builder(builderMethodName = "buildWithSpecificParamsNoID")
    public CreateTaskLogDTO(User user, Group group, OperationType operationTypeEnum, LocalDateTime operationTime, String newTaskName, Task task) {
        super(user, group, operationTypeEnum, operationTime, task);
        this.newTaskName = newTaskName;
        setOperationStr();
    }

    @Builder(builderMethodName = "buildWithOperationStringID") //buildWithOperationStringID
    public CreateTaskLogDTO(Long id, User user, Group group, OperationType operationTypeEnum, LocalDateTime operationTime, String operationString, Task task) {
        super(id, user, group, operationTypeEnum, operationTime, operationString, task);
        setSpecificFields();
    }

    @Override
    public String toString() {

        return super.toString() +  "CreateTaskLogDTO{" +
                "newTaskName='" + newTaskName + '\'' +
                ", operationString='" + operationString + '\'' +
                '}';
    }

    @Override
    public void setOperationStr() {
        this.operationString = newTaskName;
    }

    @Override
    public void setSpecificFields() {
        this.newTaskName = this.getOperationString();
    }

    @Override
    public String convertToString() {
        log.info(this.getUser().getNickname());
        log.info(this.getNewTaskName());

        return "\"" + this.getUser().getNickname() + "\" 님이 " + "\"" + this.getNewTaskName() +"\""
                + "과제를 생성하였습니다.";

    }
}

失败测试代码(使用 buildWithOperationStringID)

@Test
void createTaskLogDTO_builder_withID_test(){
    String operationString = "Task1";
    LocalDateTime now = LocalDateTime.now();

    when(mockTask.getTaskName()).thenReturn("Task1");
    when(mockUser.getNickname()).thenReturn("User1");
    when(mockGroup.getGroupName()).thenReturn("Group1");

    CreateTaskLogDTO createTaskLogDTO =  CreateTaskLogDTO.buildWithOperationStringID()
            .id(1L)
            .task(mockTask)
            .user(mockUser)
            .group(mockGroup)
            .operationString(operationString)
            .operationTime(now)
            .operationTypeEnum(OperationType.CREATE_TASK)
            .build();

    assertEquals(createTaskLogDTO.getId(),1L);
    assertEquals(createTaskLogDTO.getTask().getTaskName(),mockTask.getTaskName());
    assertEquals(createTaskLogDTO.getUser().getNickname(),mockUser.getNickname());
    assertEquals(createTaskLogDTO.getGroup().getGroupName(),mockGroup.getGroupName());
    assertEquals(createTaskLogDTO.getOperationTime(),now);
    assertEquals(createTaskLogDTO.getOperationTypeEnum(),OperationType.CREATE_TASK);
    assertEquals(operationString,createTaskLogDTO.getOperationString());
}

成功测试代码(使用 buildWithSpecificParamsNoID)

@Test
void createTaskLogDTO_build_withoutID_test(){
    when(mockTask.getTaskName()).thenReturn("Task1");
    when(mockUser.getNickname()).thenReturn("User1");
    when(mockGroup.getGroupName()).thenReturn("Group1");

    String operationString = "Task1";
    LocalDateTime now = LocalDateTime.now();

    CreateTaskLogDTO createTaskLogDTO = CreateTaskLogDTO.buildWithSpecificParamsNoID()
            .task(mockTask)
            .user(mockUser)
            .group(mockGroup)
            .operationTime(now)
            .operationTypeEnum(OperationType.CREATE_TASK)
            .newTaskName(mockTask.getTaskName())
            .build();

    assertEquals(createTaskLogDTO.getTask().getTaskName(),mockTask.getTaskName());
    assertEquals(createTaskLogDTO.getUser().getNickname(),mockUser.getNickname());
    assertEquals(createTaskLogDTO.getGroup().getGroupName(),mockGroup.getGroupName());
    assertEquals(createTaskLogDTO.getOperationTime(),now);
    assertEquals(createTaskLogDTO.getOperationTypeEnum(),OperationType.CREATE_TASK);
    assertEquals(operationString,createTaskLogDTO.getOperationString());
    assertEquals(mockTask.getTaskName(),createTaskLogDTO.getNewTaskName());
}

内容的提问来源于stack exchange,提问作者Doh Kun Lee sanity

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 23:35:19