Lombok问题:如何将@EmbeddedId定义的属性暴露给@SuperBuilder
你遇到的问题本质是Lombok的@Delegate只会给实体类本身生成委托方法,不会同步到@SuperBuilder生成的构造器中,目前Lombok没有原生支持嵌套属性平铺到Builder的特性,可以通过手动扩展SuperBuilder方法实现需求,改造成本极低且完全兼容现有架构:
第一步:改造主键类,支持toBuilder
给TheId的@Builder注解添加toBuilder = true属性,方便基于已有实例增量修改:
@Data @Builder(builderMethodName = "having", toBuilder = true) // 新增toBuilder配置 @NoArgsConstructor @AllArgsConstructor @Embeddable public class TheId { @Column(name = "name", insertable = false) private String name; @Column(name = "description", insertable = false) private String description; }
第二步:扩展BaseEntity的SuperBuilder
在BaseEntity类内部自定义SuperBuilder的抽象父类,添加name、description的链式设置方法,所有继承BaseEntity的子类都会自动继承这些方法:
@SuperBuilder @Getter @Immutable @MappedSuperclass @AllArgsConstructor @NoArgsConstructor public class BaseEntity implements Serializable { @Delegate @EmbeddedId private TheId id; @Column(name = "long_description", insertable = false) private String longDescription; // 新增:自定义SuperBuilder扩展 public static abstract class BaseEntityBuilder<C extends BaseEntity, B extends BaseEntityBuilder<C, B>> { public B name(String name) { TheId.TheIdBuilder<?, ?> idBuilder = this.id != null ? this.id.toBuilder() : TheId.having(); this.id = idBuilder.name(name).build(); return self(); } public B description(String description) { TheId.TheIdBuilder<?, ?> idBuilder = this.id != null ? this.id.toBuilder() : TheId.having(); this.id = idBuilder.description(description).build(); return self(); } } }
验证效果
改造完成后就可以直接使用你期望的链式写法:
ConcreteEntity1.having() .name("the name") .description("something") .longDescription("akjsbdkasbd") .build();
方案优势
- 完全兼容现有架构,不需要调整实体继承关系、JPA注解配置
- 所有继承
BaseEntity的子类都可以复用这两个方法,不需要重复编码 - 适配
@Immutable不可变类要求,所有修改都会生成新的TheId实例,不会破坏不可变性
内容的提问来源于stack exchange,提问作者michelson
相关产品推荐
相关产品推荐

