Шаблон для повторного использования аннотации проверки javax при «объединении» двух конечных точек

У меня есть API с двумя объектами Foo и Bar с отношением "один ко многим", т. е. каждый Bar должен ссылаться на Foo.

У меня есть конечные точки для создания как Foo, так и Bar - эти конечные точки имеют свои соответствующие DTO, определенные с проверкой javax.

public class CreateFooDto {
  @NotNull public Integer field1;
  @Length(min=1, max=8) public String field2;
}

public class CreateBarDto {
  @NotNull public Boolean field1;
  @NotEmpty public String field2;

  @NotNull public String fooId; // the foreign key to Foo
}

Теперь мне нужна новая конечная точка, которая создает Bar и Foo вместе и связывает их, а не сначала создает Foo, а затем создает Bar, передавая fooId. Мне понадобятся все те же поля с теми же проверками, за исключением обязательного CreateBarDto.fooId. В идеале я хотел бы повторно использовать проверки javax, которые я уже определил, а не повторять их.

Я хотел вложить существующие DTO в комбинированный DTO для новой конечной точки, но есть проблема с этим @NotNull на CreateBarDto.fooId — на самом деле это не требуется. Пока лучшее решение, которое я придумал, это:

public class CreateBarWithFooDto {
  @Valid public CreateFooDto foo;
  @Valid public CreateBarDto bar;
}

public class CreateBarDto {
  @NotNull public Boolean field1;
  @NotEmpty public String field2;

  public String fooId; // the foreign key to Foo
  public boolean fooIdNotRequired; // optional flag to indicate fooId not required

  @AssertTrue
  public boolean isFooIdRequired() {
    return fooIdNotRequired || fooId != null;
  }
}

Хотя это работает, это действительно довольно неуклюже. Просто интересно, может ли кто-нибудь предложить лучший шаблон для повторного использования таких проверок javax, или есть ли какие-либо аннотации javax, о которых я не знаю, которые могут помочь с этим?


person davnicwil    schedule 07.05.2019    source источник


Ответы (1)


Одним из вариантов может быть работа с группами проверки. В javadoc для javax.validation.groups говорится:

Группа определяет подмножество ограничений. Вместо проверки всех ограничений для данного графа объектов проверяется только подмножество в зависимости от целевой группы.

Каждое объявление ограничения определяет список групп, к которым оно принадлежит. Если группа явно не объявлена, ограничение принадлежит группе Default.

При применении валидации передается список целевых групп. Если ни одна группа не передается явно, используется группа javax.validation.groups.Default.

Итак, чтобы дать вам пример в вашем CreateBarDto, у нас может быть новая группа MyFirstGrup.class, которая определена только для проверки для field1 и field2

public class CreateBarDto {
  @NotNull(groups = {MyFirstGrup.class}) 
  public Boolean field1;
  @NotEmpty(groups = {MyFirstGrup.class})
  public String field2;

  @NotNull public String fooId; // the foreign key to Foo
}

Теперь вам нужно вызвать эту конкретную группу, которая обычно через

validator.validate(yourBean, MyFirstGrup.class);

Если вы используете Spring, проверьте аннотацию @Validated, которая поддерживает указание группы, которую вам нужно запустить. Подробнее здесь

person Ioan M    schedule 07.05.2019
comment
Спасибо, это отличное решение. Именно то, что я думал, может существовать с декларативным подходом на основе аннотаций. - person davnicwil; 07.05.2019