Lombok的@AllArgsConstructor注解失效问题求助
Lombok @AllArgsConstructor注解失效问题排查与解决
问题场景
父类BaseEntity定义:
@Data @NoArgsConstructor @AllArgsConstructor @SuperBuilder public class BaseEntity { protected int id; }
子类User定义:
@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @AllArgsConstructor @Data @SuperBuilder public class User extends BaseEntity{ @Email @NotNull private String mail; @Pattern(regexp = "^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,16}$") @NotNull private String password; @Pattern(regexp = "[a-zA-Z ,.'-]+") @NotNull private String name; @Pattern(regexp = "[a-zA-Z ,.'-]+") @NotNull private String surname; @NotNull private LocalDate date; private Float currentBalance; private String mobile; private String street; private String accommodationNumber; private String flatNumber; }
在Service方法中尝试通过全参构造创建User实例:
@Override public User getUserByCredentials(String mail, String password) { User user = null; Connection connection = connectionPool.getConnection(); try { PreparedStatement preparedStatement = connection.prepareStatement(GET_USER_QUERY); preparedStatement.setString(1, mail); preparedStatement.setString(2, password); ResultSet resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { user = new User(resultSet.getInt("id"), resultSet.getString("mail"), resultSet.getString("password"), resultSet.getString("name"), resultSet.getString("surname"), resultSet.getDate("date").toLocalDate(), resultSet.getFloat("balance"), resultSet.getString("mobile"), resultSet.getString("street"), resultSet.getString("accommodation_number"), resultSet.getString("flat_number")); } return user; } catch (SQLException e) { logger.warn("SQLException while getting user. Most likely request is wrong"); return null; } finally { connectionPool.closeConnection(connection); } }
报错提示不存在对应的构造方法,项目为Spring Boot,Lombok依赖版本1.18.28:
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.28</version> <scope>provided</scope> </dependency>
原因分析
Lombok的@AllArgsConstructor默认仅生成包含子类自身字段的全参构造,不会自动包含父类字段。你传入的第一个参数是父类的id,但子类生成的构造方法里没有该参数,因此报错。另外,同时使用@AllArgsConstructor和@SuperBuilder时,低版本Lombok的注解处理逻辑可能存在冲突,加剧构造方法生成异常。
解决方案
方案1:手动添加包含父类字段的全参构造
在User类中手动编写包含父类id的全参构造:
public User(int id, String mail, String password, String name, String surname, LocalDate date, Float currentBalance, String mobile, String street, String accommodationNumber, String flatNumber) { super(id); this.mail = mail; this.password = password; this.name = name; this.surname = surname; this.date = date; this.currentBalance = currentBalance; this.mobile = mobile; this.street = street; this.accommodationNumber = accommodationNumber; this.flatNumber = flatNumber; }
方案2:使用@SuperBuilder的Builder模式创建实例
既然已经添加@SuperBuilder注解,直接用Builder模式创建对象,天然支持父类字段赋值:
if (resultSet.next()) { user = User.builder() .id(resultSet.getInt("id")) .mail(resultSet.getString("mail")) .password(resultSet.getString("password")) .name(resultSet.getString("name")) .surname(resultSet.getString("surname")) .date(resultSet.getDate("date").toLocalDate()) .currentBalance(resultSet.getFloat("balance")) .mobile(resultSet.getString("mobile")) .street(resultSet.getString("street")) .accommodationNumber(resultSet.getString("accommodation_number")) .flatNumber(resultSet.getString("flat_number")) .build(); }
方案3:升级Lombok版本并调整注解顺序
将Lombok版本升级到1.18.30及以上(该版本优化了@AllArgsConstructor与@SuperBuilder的兼容性),同时调整注解顺序,把@SuperBuilder放在@AllArgsConstructor之后:
@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @Data @AllArgsConstructor @SuperBuilder public class User extends BaseEntity{ // 字段定义不变 }
升级后的依赖:
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <scope>provided</scope> </dependency>
重新编译项目后,Lombok会生成包含父类字段的全参构造。
额外检查项
- 确认IDEA已安装Lombok插件,且开启
Enable annotation processing(路径:File > Settings > Build, Execution, Deployment > Compiler > Annotation Processors) - 清理编译缓存:点击Build > Clean Project,再点击Build > Rebuild Project
内容的提问来源于stack exchange,提问作者IvanD
相关产品推荐
相关产品推荐

