1. 概述
本教程將繼續講解 Spring Data Querydsl Web Support 的第二部分。在此,我們將重點關注關聯實體以及如何通過 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 Data 存儲庫
在這一階段,我們需要創建 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);
}
}
我們正在覆蓋<em>customize()</em>方法,以配置默認綁定。在這種情況下,我們將默認方法綁定設置為 equals,應用於所有<em>String</em>屬性。
倉庫設置完成後,我們只需添加一個<em>@RestController</em>來管理 HTTP 查詢。
4. 查詢 Rest 控制器
在第一部分,我們解釋了 Query 中使用 @RestController 接口與 user 存儲庫的關係。在這裏,我們只需重用它。
此外,我們可能需要查詢 address 表,因此,我們將添加類似的方法:
@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 查詢,並連接了 user 實體與新的 address 實體。因此,我們現在可以對 address 屬性進行過濾查詢。
讓我們檢索所有居住在西班牙的用户:
/users?addresses.country=Spain
@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 為 Web 客户端提供了一種簡單而強大的替代方案,用於創建動態查詢;這充分體現了該框架的強大之處。
在第一部分中,我們瞭解到如何從一個表中檢索數據;因此,現在我們可以添加連接多個表的查詢,為 Web 客户端提供更好的過濾體驗,直接在他們發出的 HTTP 請求上進行過濾。