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

自定义Lombok Builder后无法访问User实体字段的问题解决

问题:自定义Lombok Builder导致字段方法丢失

你在使用Lombok的@Builder自定义User类的Builder来维护User和UserProfile的一对一双向关联时,出现了.email()等字段方法找不到的错误,原因是你完全重写了UserBuilder类,导致Lombok无法自动生成其他字段的Builder方法。

代码问题分析

你自定义了完整的UserBuilder类,Lombok会认为你要完全控制Builder的实现,因此不会自动生成email、password、roles等字段对应的Builder方法,这就是调用.email()时报错的根本原因。

修复方案

1. 修正Builder实现,保留Lombok自动生成的字段方法

不要完全重写UserBuilder类,而是仅重写build()方法来维护双向关联,让Lombok自动生成其他字段的Builder方法:

@Setter
@Getter
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class User {

    @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(
            name = "UUID",
            strategy = "org.hibernate.id.UUIDGenerator",
            parameters = {
                    @Parameter(
                            name = "uuid_gen_strategy_class",
                            value = "org.hibernate.id.uuid.CustomVersionOneStrategy"
                    )
            }
    )
    @Column(columnDefinition = "CHAR(36)")
    @Type(type = "uuid-char")
    private UUID userId;

    // 补充你遗漏的业务字段
    private String email;
    private String password;
    private Set<Entitlement> roles;

    @OneToOne(
            mappedBy = "user",
            cascade = CascadeType.ALL,
            fetch = FetchType.LAZY,
            optional = false
    )
    private UserProfile profile;

    // 仅重写build方法维护双向关联,不覆盖整个Builder
    public static class UserBuilder {
        @Override
        public User build() {
            User user = super.build();
            // 建立双向关联
            if (user.getProfile() != null) {
                user.getProfile().setUser(user);
            }
            return user;
        }
    }
}

修改后,User.builder()会自动生成.email()、.password()、.roles()等所有字段的方法,同时在build时自动维护User和UserProfile的双向关联。

2. 更优的一对一关联实现(推荐)

使用Hibernate的@MapsId让UserProfile共享User的主键,避免重复生成UUID,更符合一对一关联的最佳实践:

修改UserProfile类

@Setter
@Getter
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class UserProfile {

    @Id
    @Column(columnDefinition = "CHAR(36)")
    @Type(type = "uuid-char")
    private UUID userId;

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId // 让当前实体的主键关联到User的主键
    @ToString.Exclude
    private User user;

    // 补充业务字段
    private String firstName;
    private String lastName;
}

保持User类的Builder修改

依然使用上述重写build()方法的方式维护双向关联,这样UserProfile的主键会自动和关联的User主键保持一致,无需单独生成UUID,减少冗余。

验证修改后的Mapper代码

修改后你的RegisterUserRequestToUserMapper代码可以正常运行:

@Component
@RequiredArgsConstructor
public class RegisterUserRequestToUserMapper {

    private final PasswordEncoder passwordEncoder;

    public User map(RegisterUserRequest request) {
        return User.builder()
                .email(request.getEmail())
                .password(passwordEncoder.encode(request.getPassword()))
                .roles(Set.of(Entitlement.USER))
                .profile(
                        UserProfile.builder()
                                .firstName(request.getFirstName())
                                .lastName(request.getLastName())
                                .build()
                )
                .build();
    }
}

内容的提问来源于stack exchange,提问作者Prashant

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 14:45:28