Skip to main content

7. Comprehensive Query

So far, we've quickly demonstrated the following features

Now, let's combine all of the above features into a relatively powerful query

Again, there are two ways to develop

  • Query dynamic entities

  • Query static DTOs

Query Dynamic Entities

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);
}
}
info

Here, the 'findBooks' method has too many parameters. This doesn't matter to Kotlin, but it may not be a good design for Java.

If your project is based on the Java language, you can choose to reduce the number of parameters in the Java language by distilling all or some of the parameters into an object.

However, this does not provide substantial benefit to the example presentation here, therefore, we do not do so in order to maintain a high degree of consistency between the Java and Kotlin examples.

The user can use it like this (considering that Java doesn't have a good way to simplify the invocation to a method with many parameters, just a demonstration the kotlin invocation)

val bookRepository = ...Omitted...

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()
}
}
)

The result is

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
}

Query Static 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);
}
}
info

Here, the 'findBooks' method has too many parameters. This doesn't matter to Kotlin, but it may not be a good design for Java.

If your project is based on the Java language, you can choose to reduce the number of parameters in the Java language by distilling all or some of the parameters into an object.

However, this does not provide substantial benefit to the example presentation here, therefore, we do not do so in order to maintain a high degree of consistency between the Java and Kotlin examples.

To demonstrate the invocation, let's first use the DTO language to automatically generate a DTO type that implements the View<Book> interface.

Create any file with the dto extension under the src/main/dto folder, and edit the code as follows:

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

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

Compile the project, a java/kotlin class named BookView will be automatically generated.

The user can use it like this (considering that Java doesn't have a good way to simplify the invocation to a method with many parameters, just a demonstration the kotlin invocation)

val bookRepository = ...Omitted...

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
}