Перейти к основному содержимому

Язык запросов REST для нескольких таблиц с веб-поддержкой Querydsl

· 3 мин. чтения

1. Обзор

В этом руководстве мы продолжим вторую часть веб-поддержки Spring Data Querydsl. Здесь мы сосредоточимся на связанных объектах и на том, как создавать запросы через HTTP.

Следуя той же конфигурации, что и в первой части, мы создадим проект на основе Maven. Пожалуйста, обратитесь к оригинальной статье, чтобы узнать, как настроить основы.

2. Сущности

Во-первых, давайте добавим новую сущность ( Адрес) , создающую связь между пользователем и его адресом. Мы использовали отношение OneToOne для простоты.

Следовательно, у нас будут следующие классы:

@Entity 
public class User {

@Id
@GeneratedValue
private Long id;

private String name;

@OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
private Address addresses;

// getters & setters
}
@Entity 
public class Address {

@Id
@GeneratedValue
private Long id;

private String address;

private String country;

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

// getters & setters
}

3. Хранилища данных Spring

На этом этапе мы должны создать репозитории Spring Data, как обычно, по одному для каждой сущности. Обратите внимание, что эти репозитории будут иметь конфигурацию Querydsl.

Давайте посмотрим на репозиторий AddressRepository и объясним, как работает конфигурация фреймворка:

public interface AddressRepository extends JpaRepository<Address, Long>, 
QuerydslPredicateExecutor<Address>, QuerydslBinderCustomizer<QAddress> {

@Override
default void customize(QuerydslBindings bindings, QAddress root) {
bindings.bind(String.class)
.first((SingleValueBinding<StringPath, String>) StringExpression::eq);
}
}

Мы переопределяем метод custom() , чтобы настроить привязку по умолчанию. В этом случае мы настроим привязку метода по умолчанию, чтобы она была равна для всех свойств String .

После того, как репозиторий настроен, нам просто нужно добавить @RestController для управления HTTP-запросами.

4. Контроллер запроса остатка

В первой части мы объяснили Query @RestController через пользовательский репозиторий, здесь мы просто будем использовать его повторно.

Кроме того, мы можем захотеть запросить таблицу адресов ; поэтому для этого мы просто добавим аналогичный метод:

@GetMapping(value = "/addresses", produces = MediaType.APPLICATION_JSON_VALUE)
public Iterable<Address> queryOverAddress(
@QuerydslPredicate(root = Address.class) Predicate predicate) {
BooleanBuilder builder = new BooleanBuilder();
return addressRepository.findAll(builder.and(predicate));
}

Давайте создадим несколько тестов, чтобы увидеть, как это работает.

5. Интеграционное тестирование

Мы включили тест, чтобы проверить, как работает Querydsl. Для этого мы используем инфраструктуру MockMvc для имитации HTTP-запросов пользователя , присоединяющегося к этому объекту с новым: адресом. Поэтому теперь мы можем делать запросы, фильтрующие атрибуты адреса .

Давайте получим всех пользователей, живущих в Испании:

/users?addresses.country=Испания

@Test
public void givenRequest_whenQueryUserFilteringByCountrySpain_thenGetJohn() throws Exception {
mockMvc.perform(get("/users?address.country=Spain")).andExpect(status().isOk()).andExpect(content()
.contentType(contentType))
.andExpect(jsonPath("$", hasSize(1)))
.andExpect(jsonPath("$[0].name", is("John")))
.andExpect(jsonPath("$[0].address.address", is("Fake Street 1")))
.andExpect(jsonPath("$[0].address.country", is("Spain")));
}

В результате Querydsl сопоставит предикат, отправленный по HTTP, и сгенерирует следующий сценарий SQL:

select user0_.id as id1_1_, 
user0_.name as name2_1_
from user user0_
cross join address address1_
where user0_.id=address1_.user_id
and address1_.country='Spain'

6. Заключение

Подводя итог, мы увидели, что Querydsl предлагает веб-клиентам очень простую альтернативу созданию динамических запросов; еще одно мощное использование этой структуры.

В части I мы видели, как извлекать данные из одной таблицы; следовательно, теперь мы можем добавлять запросы, объединяющие несколько таблиц, предлагая веб-клиентам лучший опыт фильтрации непосредственно через HTTP-запросы, которые они делают.

Реализация этого примера может быть проверена в проекте GitHub — это проект на основе Maven, поэтому его легко импортировать и запускать как есть.