跳到主要内容

7. 综合查询

截止到目前为止,我们快速展示了如下功能

现在,我们把以上所有功能综合起来,形成一个相对强大的查询

同样,存在两种开发方式

  • 查询动态实体

  • 查询静态DTO

查询动态实体

public class BookRepository {

private static final BookTable T = BookTable.$;

private final JSqlClient sqlClient;

public BookRepository(JSqlClient sqlClient) {
this.sqlClient = sqlClient;
}

public Page<Book> findBooks(
int pageIndex,
int pageSize,
@Nullable String sortCode,
@Nullable Fetcher<Book> fetcher,
@Nullable String name,
@Nullable BigDecimal minPrice,
@Nullable BigDecimal maxPrice,
@Nullable String storeName,
@Nullable String storeWebsite,
@Nullable String authorName
) {
return sqlClient
.createQuery(T)
.where(T.name().ilikeIf(name))
.where(T.price().betweenIf(minPrice, maxPrice))
.where(T.store().name().ilikeIf(storeName))
.where(T.store().website().ilikeIf(storeWebsite))
.where(
T.authors(author ->
Predicate.or(
author.firstName().ilikeIf(authorName),
author.lastName().ilikeIf(authorName)
)
)
)
.orderBy(
Order.makeOrders(
T,
sortCode != null ?
sortCode :
"name asc, edition desc"
)
)
.select(T.fetch(fetcher))
.fetchPage(pageIndex, pageSize);
}
}
信息

这里,findBooks方法的参数很多。这对Kotlin而言无所谓,但是对Java而言可能不是一个好的设计。

如果你的项目是基于Java语言开发的,面对这种情况,你可以选择将所有参数或部分参数提炼成一个参数对象,来减少Java语言下的参数数量。

然而,这样做对这里的例子展示没有实质性的好处,再加上为了保持Java和Kotlin例子的高度一致性,并没有这样做。

用户可以如此调用 (考虑到Java没有很好手段来简化对参数较多的方法的调用,仅示范kotlin调用)

val bookRepository = ......

val page = bookRepository.findBooks(
pageIndex = 1,
pageSize = 2,
name = "GraphQL",
maxPrice = BigDecimal(60),
authorName = "alex",
fetcher = newFetcher(Book::class).by {
allScalarFields()
store {
name()
}
authors {
firstName()
lastName()
}
}
)

得到如下结果

Page{
rows=[
{
"id":1,
"name":"Learning GraphQL",
"edition":1,
"price":50.00,
"store":{"id":1,"name":"O'REILLY"},
"authors":[
{"id":2,"firstName":"Alex","lastName":"Banks"},
{"id":1,"firstName":"Eve","lastName":"Procello"}
]
}
],
totalRowCount=3,
totalPageCount=2
}

查询静态DTO

public class BookRepository {

private static final BookTable T = BookTable.$;

private final JSqlClient sqlClient;

public BookRepository(JSqlClient sqlClient) {
this.sqlClient = sqlClient;
}

public <V extends View<Book>> Page<V> findBooks(
int pageIndex,
int pageSize,
@Nullable String sortCode,
@Nullable Class<V> viewType,
@Nullable String name,
@Nullable BigDecimal minPrice,
@Nullable BigDecimal maxPrice,
@Nullable String storeName,
@Nullable String storeWebsite,
@Nullable String authorName
) {
return sqlClient
.createQuery(T)
.where(T.name().ilikeIf(name))
.where(T.price().betweenIf(minPrice, maxPrice))
.where(T.store().name().ilikeIf(storeName))
.where(T.store().website().ilikeIf(storeWebsite))
.where(
T.authors(author ->
Predicate.or(
author.firstName().ilikeIf(authorName),
author.lastName().ilikeIf(authorName)
)
)
)
.orderBy(
Order.makeOrders(
T,
sortCode != null ?
sortCode :
"name asc, edition desc"
)
)
.select(T.fetch(viewType))
.fetchPage(pageIndex, pageSize);
}
}
信息

这里,findBooks方法的参数很多。这对Kotlin而言无所谓,但是对Java而言可能不是一个好的设计。

如果你的项目是基于Java语言开发的,面对这种情况,你可以选择将所有参数或部分参数提炼成一个参数对象,来减少Java语言下的参数数量。

然而,这样做对这里的例子展示没有实质性的好处,再加上为了保持Java和Kotlin例子的高度一致性,并没有这样做。

为了演示调用,我们先使用DTO语言自动生成一个实现了View<Book>接口的DTO类型。

src/main/dto目录下新建任何扩展名为dto的文件,编写如下代码

export com.yourcompany.yourproject.model.Book
-> package com.yourcompany.yourproject.model.dto

BookView {
#allScalars
store {
id
name
}
authors {
id
firstName
lastName
}
}

编译,自动生成名为BookView的Java/Kotlin类。

用户可以如此调用 (考虑到Java没有很好手段来简化对参数较多的方法的调用,仅示范kotlin调用)

val bookRepository = ......

val page = bookRepository.findBooks(
name = "GraphQL",
maxPrice = BigDecimal(60),
authorName = "alex",
viewType = BookView::class
)

得到如下结果

Page{
rows=[
BookView(
id=1,
name=Learning GraphQL,
edition=1,
price=50.00,
store=BookView.TargetOf_store(id=1, name=O'REILLY),
authors=[
BookView.TargetOf_authors(id=2, firstName=Alex, lastName=Banks),
BookView.TargetOf_authors(id=1, firstName=Eve, lastName=Procello)
]
)
],
totalRowCount=3,
totalPageCount=2
}