Lombok -将@EmbeddedId字段暴露给@SuperBuilder



是否有办法将@EmbeddedId中定义的属性暴露给@SuperBuilder?

// Composite id class
@Data
@Builder(builderMethodName = "having")
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class TheId {
@Column(name = "name", insertable = false)
private String name;
@Column(name = "description", insertable = false)
private String description;
}
// Base entity class
@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;
}
// Concreate entity over database view
@Entity
@Table(name = "view_number_1")
@Getter
@Setter
@Immutable
@AllArgsConstructor(staticName = "of")
@SuperBuilder(builderMethodName = "having")
public class ConcreteEntity1 extends BaseEntity {}

我希望能写出这样的代码:

ConcreateEntity1.having()
.name("the name")
.description("something")
.longDescription("akjsbdkasbd")
.build();

不是

ConcreateEntity1.having()
.id(TheId.having()
.name("the name")
.description("something")
.build())
.longDescription("akjsbdkasbd")
.build();

整个概念背后的原因:相同名称的列出现在多个视图中,因此为它们都使用一个基类是合乎逻辑的。虽然实体本身是不可变的(基于数据库视图),我想在测试中使用builder,这就是为什么我想让他们如上所述。

没有自动将委托插入@(Super)Builder的方法。但是,如果您的委托类(本例中为TheId)不包含太多字段,则可以手动将相应的setter方法添加到构建器类中。只需添加正确的构建器类头,将代码放入其中,Lombok将添加所有您不需要手动编写的剩余代码。

无可否认,这有点棘手。@SuperBuilder生成的代码非常复杂,您不希望添加太多手工的东西,因为您希望保留Lombok的优点:如果您更改了带注释的类中的某些内容,您不会希望重写所有手工方法。因此,这个解决方案试图以一点点性能/内存浪费为代价来保持大部分自动化。

@SuperBuilder(builderMethodName = "having")
public class BaseEntity {
@Delegate
private TheId id;
private String longDescription;
public static abstract class BaseEntityBuilder<C extends BaseEntity, B extends BaseEntityBuilder<C, B>> {
private TheId.TheIdBuilder theIdBuilder = TheId.having();

// Manually implement all delegations.
public B name(String name) {
theIdBuilder.name(name);
// Instantiating every time you call the setter is not optimal, 
// but better than manually writing the constructor.
id = theIdBuilder.build();
return self();
}
public B description(String description) {
theIdBuilder.description(description);
id = theIdBuilder.build();
return self();
}

// Make this method invisible. 
@SuppressWarnings("unused")
private B id() {
return self();
}
}
}

值得吗?这是一个品味问题,以及它在多大程度上提高了构建器的适用性/可用性/可读性。

既然你在id中使用了@Delegate注释,那么你应该能够直接从BaseEntity class中设置/获取TheId字段。

您可以在Project Lombok中了解更多信息。

最新更新