-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME.in
150 lines (119 loc) · 5.09 KB
/
README.in
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
## Usage
### JOOQ
The `jqpage` package uses [jooq](https://www.jooq.org/). APIs are expressed
in terms of `jooq` query structures.
### Sakila
This documentation is written using example data from the [sakila](https://github.com/jOOQ/sakila)
database.
### Offset Pagination
Offset pagination is provided by the `JQOffsetPagination` class. Offset
pagination is generally considered inferior to
[keyset pagination](#keyset-pagination) but may be necessary when executing
queries that are too complex to use keyset pagination. The `JQOffsetPagination`
class implements pagination in a single database round trip by calculating
page boundary offsets using window functions. See
[Calculating Pagination Metadata](https://blog.jooq.org/calculating-pagination-metadata-without-extra-roundtrips-in-sql/)
for the general technique.
Assuming a base query that selects everything from an `ACTOR` table:
```
DSLContext context = ...
final var baseQuery =
context.selectFrom(ACTOR)
.orderBy(ACTOR.ACTOR_ID);
```
The `JQOffsetPagination.paginate()` method can paginate the query. The method
takes a base query, a list of fields used in the `ORDER BY` clause, a number
specifying the desired number of results per page, an offset value, and
a function from `Record` values to values of your application's domain
types. The method returns a `JQPage` value that contains a list of results,
a page number, and a count of the total number of pages that could be returned.
```
record Person(
int id,
String nameFirst,
String nameLast)
{
}
Person toActor(
final Record record)
{
return new Person(
record.getValue(ACTOR.ACTOR_ID, Integer.class).intValue(),
record.getValue(ACTOR.FIRST_NAME, String.class),
record.getValue(ACTOR.LAST_NAME, String.class)
);
}
final JQPage<Person> page =
JQOffsetPagination.paginate(
context,
baseQuery,
List.of(ACTOR.ACTOR_ID),
75L,
0L,
this::toActor
);
```
### Keyset Pagination
Keyset pagination is provided by the `JQKeysetRandomAccessPagination` class.
The `JQKeysetRandomAccessPagination.createPageDefinitions()` function takes
an instance of the immutable `JQKeysetRandomAccessPaginationParameters` class.
The `JQKeysetRandomAccessPaginationParameters` class has the following
properties:
|Name| Description |
|----|----------------------------------------------------------------------------------------------------------------------------------------------------------|
|context| The `jooq` DSL context used to execute queries. |
|table| A _table_ expression. Typically the name of a table, or a set of table joins. All columns referenced elsewhere must be present in this table expression. |
|sortFields|The list of fields by which to sort the resulting rows|
|whereConditions|The list of conditions by which to filter rows. An empty list means no `WHERE` clause.|
|groupBy|A list of fields to use in a `GROUP BY` clause. An empty list means no `GROUP BY`.|
|pageSize|The maximum desired size of a page.|
|distinct|Whether to use SELECT DISTINCT for the processed rows.|
Due to the large number of parameters, the
`JQKeysetRandomAccessPaginationParameters` class provides a mutable builder
for constructing instances of the class.
The method returns a list of
`JQKeysetRandomAccessPageDefinition` structures that individually contain
all the information required to seek directly to any page of the executed
query in more or less constant time. The `JQKeysetRandomAccessPagination`
class assumes the use of a database that supports window functions.
See [Faster SQL Pagination with Keysets](https://blog.jooq.org/faster-sql-pagination-with-keysets-continued/)
for the general technique.
```
Person toCustomer(
final Record record)
{
return new Person(
record.getValue(CUSTOMER.CUSTOMER_ID, Integer.class).intValue(),
record.getValue(CUSTOMER.FIRST_NAME, String.class),
record.getValue(CUSTOMER.LAST_NAME, String.class)
);
}
final List<JQField> orderBy =
List.of(
new JQField(CUSTOMER.FIRST_NAME, ASCENDING),
new JQField(CUSTOMER.LAST_NAME, DESCENDING),
);
final JQKeysetRandomAccessPaginationParameters parameters =
JQKeysetRandomAccessPaginationParameters.forTable(CUSTOMER)
.addWhereCondition(CUSTOMER.FIRST_NAME.like("%I%"))
.addSortField(new JQField(CUSTOMER.FIRST_NAME, ASCENDING))
.addSortField(new JQField(CUSTOMER.LAST_NAME, DESCENDING))
.setPageSize(75L)
.build();
final List<JQKeysetRandomAccessPageDefinition> pages =
JQKeysetRandomAccessPagination.createPageDefinitions(context, parameters);
final JQKeysetRandomAccessPageDefinition page = pages.get(1);
final List<Person> records =
page.query(context)
.fetch()
.map(this::toCustomer);
// Or, equivalently:
final List<Person> records =
context.selectFrom(CUSTOMER)
.where(CUSTOMER.FIRST_NAME.like("%I%"))
.orderBy(page.orderBy())
.seek(page.seek())
.limit(page.limit())
.fetch()
.map(this::toCustomer);
```