Как использовать lombok @Builder для хранения разных значений? - PullRequest
2 голосов
/ 22 июня 2019

У меня есть следующий объект 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;
  }
}

Из документации там появляется аннотация ObtainVia, которую я могу использовать, но я не уверен, как ее обойти (нет примера в документе), и особенно, поскольку я хочу только myTags быть специфической для строителя вещью, а не подвергаться воздействию самого основного класса.

Ответы [ 2 ]

0 голосов
/ 28 июня 2019

Вы можете использовать @Accessors для того, что вы спрашиваете:

Post

@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;
    }
}

PostTags

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

Когда вы используете @Accessors(chain = true), сеттеры вернут ссылку this вместо void, и ваш код будет действовать следующим образом:

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

Есливы хотите, чтобы ваш код был больше похож на компоновщик, а затем добавьте значение fluent к аннотации: @Accessors(chain = true, fluent = true)

Это удалит set<Something> из сеттеров и просто использует имя полей, а затемваш код будет выглядеть так:

Post post = new Post().id(id).content("hello").tags("aaa", "bbb");
0 голосов
/ 22 июня 2019

ObtainVia работает только для toBuilder, так что в этом случае это мало поможет.

Я предлагаю следующий подход.

Сначала добавьте фабричный метод в PostTag, например, createTag(String). Этот метод устанавливает tag только в том случае, если он создает, и оставляет все остальное null. Статически импортируйте его в класс, где вы хотите использовать PostBuilder.

Далее, используйте @Singular на tags. Тогда вы можете написать:

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

Наконец, настройте метод build() так, чтобы он сначала создал экземпляр Post (как ненастроенный метод build()), а затем установил этот вновь созданный экземпляр Post как post во всех PostTag экземпляров. Взгляните на код delombok ed, чтобы убедиться, что при настройке компоновщика вы используете правильный класс построителя и заголовки методов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...