Статьи

Поддержка спецификации DDD в Hades

В первой части этой серии о Аиде я говорил о запросах и поддержке поиска. В этой статье я расскажу о другой полезной функции Hades под названием Specification. Спецификация — это концепция проектирования, управляемая доменом, в которой вы определяете предикат, чтобы проверить, соответствует ли объект критериям или нет. Аид обеспечивает поддержку Спецификации в форме Спецификации интерфейса, которая является оберткой над JPA Criteria API. Интерфейс Спецификации предоставляет метод обратного вызова, который получает  CriteriaBuilder , CriteriaQuery <T> и Root <T> в качестве аргументов и возвращает Предикат.          

public interface Specification<T> {

Predicate toPredicate(Root<T> root, CriteriaQuery<T> query,
CriteriaBuilder builder);
}

Интерфейс Hades GenericDao предоставляет два метода с поддержкой спецификаций.

List<T> readAll(final Specification<T> spec); // return list of entities matching spec
Page<T> readAll(final Specification<T> spec, final Pageable pageable); // returns a Page of entities matching the spec

 

Спецификация предлагает:

  1. Вы можете легко подключить новые стратегии соответствия: Спецификация является стратегическим интерфейсом, поэтому легко добавлять новые критерии без изменения API. Таким образом, вы можете очень легко добавить такие стратегии, как bookByAuthorName или bookWithPriceLessThan или bookByAuthorWithPriceInBetween.
    public static Specification<Book> bookByAuthorName(final String value) {
    return new Specification<Book>() {

    public Predicate toPredicate(Root<Book> root, CriteriaQuery<Book> query, CriteriaBuilder builder) {
    return builder.equal(root.get("author"), value);
    }
    };
    }

    public static Specification<Book> withPriceBetween(final double start, final double end) {
    return new Specification<Book>() {

    public Predicate toPredicate(Root<Book> root, CriteriaQuery<Book> query, CriteriaBuilder builder) {
    return builder.between(root.<Double> get("price"), start, end);
    }
    };
    }

    и код клиента

    @Test
    public void shouldFindBookByAuthorNameSpecification() throws Exception {
    List<Book> allBooks = bookDao.readAll(BookSpecifications.bookByAuthorName("shekhar"));
    assertThat(allBooks.size(), is(equalTo(1)));
    }
  2. Вы можете избежать смешения разных сущностейПредположим, что мы хотим найти все книги, написанные конкретным автором, а Автор является объектом нашего приложения. Таким образом, если мы не используем спецификацию, нам нужно будет добавить метод findAllBooksByAuthor (Автор, автор). Таким образом, наш дао домена Book теперь тесно связан с Author, и по мере того, как мы продолжаем добавлять разные сущности, все становится грязным. Таким образом, с помощью спецификации мы можем избежать этого беспорядка.
  3. Вы можете уменьшить код котельной пластины  : со Спецификацией вам не нужно беспокоиться о написании кода котельной пластины при создании  CriteriaBuilderCriteriaQuery <T>  и  Root <T>.  Вы получаете все это с помощью обратного вызова.
  4. Вы можете комбинировать спецификации  : одна из самых крутых особенностей спецификаций заключается в том, что вы можете создавать сложные спецификации, объединяя различные спецификации вместе. Hades предоставляет служебный класс под названием Спецификации, который предоставляет служебные методы для объединения экземпляров Спецификации. Например
     public static Specification<Book> bookByAuthorAndPriceBetween(final String authorName, final double priceStart, final double priceEnd) {
    return where(bookByAuthorName(authorName)).and(withPriceBetween(priceStart, priceEnd));
    }