【问题标题】:How do I use lombok @Builder to store different values?如何使用 lombok @Builder 存储不同的值?
【发布时间】:2019-06-22 14:22:48
【问题描述】:

我有以下 JPA 实体

@Data
@Builder
public class Post {
  @Id
  @GeneratedValue
  UUID id;

  @OneToMany
  Set<PostTags> tags;

  String content;
}

@Data
public class PostTag {
  @Id
  @GeneratedValue
  UUID id;

  @OneToOne
  Post post;

  String tag;
}

使用 lombok @Builder 我希望能够执行以下操作

Post post = Post.builder()
  .tags("hello", "world")
  .content("Hello world")
  .build();

我假设我需要一个自定义构建器,类似于

public static class PostBuilder {
  private Set<String> myTags = new HashSet<>();
  public PostBuilder tags(String... tags) {
    myTags.addAll(Arrays.asList(tags));
    return this;
  }
}

documentation 中,我可以使用ObtainVia 注释,但我不确定如何绕过它(文档上没有示例),特别是因为我只希望myTags 成为构建器具体的事情,而不是暴露在主类本身。

【问题讨论】:

    标签: java lombok


    【解决方案1】:

    ObtainVia 仅适用于 toBuilder,因此在这种情况下不会有太大帮助。

    我建议以下方法。

    首先,在PostTag 中添加一个工厂方法,例如createTag(String)。此方法仅在它创建的实例中设置tag,并保留其他所有内容null。将其静态导入到要使用PostBuilder的类中。

    接下来,在tags 上使用@Singular。然后你可以写:

    Post post = Post.builder()
       .tag(createTag("hello"))
       .tag(createTag("world"))
       .content("Hello world")
       .build();
    

    最后,自定义build() 方法,使其首先创建Post 实例(就像未自定义的build() 方法一样),然后将这个新创建的Post 实例设置为post 在所有PostTag实例。 查看delomboked 代码,确保在自定义构建器时使用正确的构建器类和方法头。

    【讨论】:

    • 我想使用字符串标签作为参数,但下属集合是 PostTag 而不是字符串
    • 哦,没看到。如何从字符串构建PostTag 的实例?只需设置tag 并保留其他所有内容null
    • 我想过,但因为 PostTag 需要“发布”,所以有点鸡和蛋的问题
    • 我更新了我的答案。随意询问是否有不清楚的地方(或者我是否又错过了什么:-))。
    • 谢谢,但是 PostTag 从哪里得到它的“post”值集?
    【解决方案2】:

    您可以使用@Accessors 来满足您的要求:

    发帖

    @Data
    @Accessors(chain = true)
    public class Post {
        @Id
        @GeneratedValue
        private UUID id;
    
        @OneToMany
        private Set<PostTags> tags;
    
        private String content;
    
        public Post tags(String... tags) {
            Arrays.stream(tags)
                    .map(tag -> PostTags.builder().tag(tag).build())
                    .forEach(this.tags::add);
            return this;
        }
    }
    

    帖子标签

    @Data
    @Builder
    public class PostTags {
        @Id
        @GeneratedValue
        private UUID id;
        @OneToOne
        private Post post;
        private String tag;
    }
    

    当您使用@Accessors(chain = true) 时,setter 将返回this 引用而不是void,然后您的代码将这样操作:

    Post post = new Post().setId(id).tags("aaa", "bbb");
    

    如果您希望您的代码更类似于 builder,请在注释中添加 fluent 值:@Accessors(chain = true, fluent = true)

    它会从 setter 中删除 set&lt;Something&gt; 并只使用字段的名称,然后您的代码将如下所示:

    Post post = new Post().id(id).content("hello").tags("aaa", "bbb");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-03
      • 1970-01-01
      • 2018-08-09
      • 1970-01-01
      • 2020-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多