В первой части этой серии о Аиде я говорил о запросах и поддержке поиска. В этой статье я расскажу о другой полезной функции 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
Спецификация предлагает:
- Вы можете легко подключить новые стратегии соответствия: Спецификация является стратегическим интерфейсом, поэтому легко добавлять новые критерии без изменения 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)));
} - Вы можете избежать смешения разных сущностейПредположим, что мы хотим найти все книги, написанные конкретным автором, а Автор является объектом нашего приложения. Таким образом, если мы не используем спецификацию, нам нужно будет добавить метод findAllBooksByAuthor (Автор, автор). Таким образом, наш дао домена Book теперь тесно связан с Author, и по мере того, как мы продолжаем добавлять разные сущности, все становится грязным. Таким образом, с помощью спецификации мы можем избежать этого беспорядка.
- Вы можете уменьшить код котельной пластины : со Спецификацией вам не нужно беспокоиться о написании кода котельной пластины при создании CriteriaBuilder , CriteriaQuery <T> и Root <T>. Вы получаете все это с помощью обратного вызова.
- Вы можете комбинировать спецификации : одна из самых крутых особенностей спецификаций заключается в том, что вы можете создавать сложные спецификации, объединяя различные спецификации вместе. Hades предоставляет служебный класс под названием Спецификации, который предоставляет служебные методы для объединения экземпляров Спецификации. Например
public static Specification<Book> bookByAuthorAndPriceBetween(final String authorName, final double priceStart, final double priceEnd) {
return where(bookByAuthorName(authorName)).and(withPriceBetween(priceStart, priceEnd));
}