自定义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
相关产品推荐
相关产品推荐

