Lombok @AllArgsConstructor未包含父类属性的泛型抽象类继承问题
解决方案:泛型抽象父类继承下的Lombok+JPA配置优化
1. 修正主键字段映射(解决emp_id映射问题)
父类的id字段需要映射到数据库的emp_id列,无需修改父类字段名(避免破坏通用Service复用逻辑),直接在子类使用JPA的@AttributeOverride注解覆盖字段映射配置即可:
@Entity @Table(name = "employee") @EqualsAndHashCode(callSuper = true) @Getter @Setter @NoArgsConstructor public class Employee extends GenericEntity<Employee> implements Serializable { // 覆盖父类id字段的映射规则,指定对应数据库列名emp_id @AttributeOverride(name = "id", column = @Column(name = "emp_id", nullable = false, updatable = false)) private Long id; @Column(name = "first_name", nullable = false) private String firstName; @Column(name = "last_name", nullable = false) private String lastName; // 其余映射字段... }
2. 用Lombok生成目标构造器
方式一:生成指定参数的构造器(匹配需求)
如果需要生成Employee(Long empId, String firstName, String lastName)这类构造器,可结合@RequiredArgsConstructor和@NonNull实现:
@Entity @Table(name = "employee") @EqualsAndHashCode(callSuper = true) @Getter @Setter @NoArgsConstructor @RequiredArgsConstructor // 生成包含所有@NonNull字段的构造器 public class Employee extends GenericEntity<Employee> implements Serializable { @AttributeOverride(name = "id", column = @Column(name = "emp_id", nullable = false, updatable = false)) @NonNull private Long id; @Column(name = "first_name", nullable = false) @NonNull private String firstName; @Column(name = "last_name", nullable = false) @NonNull private String lastName; // 其余映射字段... }
Lombok会自动生成如下构造器(自动调用父类的@AllArgsConstructor构造器传入id):
public Employee(@NonNull Long id, @NonNull String firstName, @NonNull String lastName) { super(id); this.id = id; this.firstName = firstName; this.lastName = lastName; }
调用时用变量名empId即可保证可读性:
Long empId = 1L; Employee emp = new Employee(empId, "John", "Doe");
方式二:用@Builder生成灵活构造器
如果需要更灵活的对象构建方式,推荐使用@Builder,支持任意参数组合:
@Entity @Table(name = "employee") @EqualsAndHashCode(callSuper = true) @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder(toBuilder = true) public class Employee extends GenericEntity<Employee> implements Serializable { @AttributeOverride(name = "id", column = @Column(name = "emp_id", nullable = false, updatable = false)) private Long id; @Column(name = "first_name", nullable = false) private String firstName; @Column(name = "last_name", nullable = false) private String lastName; // 其余映射字段... }
调用示例:
Employee emp = Employee.builder() .id(1L) // 对应数据库emp_id列 .firstName("John") .lastName("Doe") .build();
3. 保障通用Service复用性
由于子类保留了父类id字段的定义(仅覆盖映射规则),通用Service可直接基于GenericEntity<T>编写:
public abstract class GenericService<T extends GenericEntity<T>> { public T findById(Long id) { // 通用查询逻辑 return null; } // 其他通用方法:save、delete等 } @Service public class EmployeeService extends GenericService<Employee> { // 复用父类方法,按需添加自定义逻辑 }
关键注意事项
- 父类必须保留
@AllArgsConstructor,否则子类Lombok构造器无法自动调用父类构造器传入id @AttributeOverride是JPA规范写法,不会破坏继承结构,完美适配通用代码复用场景- 若无需非空校验,可去掉
@NonNull,改用@AllArgsConstructor+@Builder组合实现灵活构造
内容的提问来源于stack exchange,提问作者AbdoCherry
相关产品推荐
相关产品推荐

