捲動
捲動是一種更細緻的方法,用於迭代處理較大的結果集區塊。捲動包含穩定的排序、捲動類型(基於偏移量或鍵集的捲動)和結果限制。您可以使用屬性名稱定義簡單的排序表達式,並透過查詢衍生使用 Top
或 First
關鍵字來定義靜態結果限制。您可以串連表達式以將多個條件收集到一個表達式中。
捲動查詢會回傳 Window<T>
,讓您取得元素的捲動位置以提取下一個 Window<T>
,直到您的應用程式已消耗整個查詢結果。類似於透過取得下一批結果來消耗 Java Iterator<List<…>>
,查詢結果捲動讓您可以透過 Window.positionAt(…)
存取 ScrollPosition
。
Window<User> users = repository.findFirst10ByLastnameOrderByFirstname("Doe", ScrollPosition.offset());
do {
for (User u : users) {
// consume the user
}
// obtain the next Scroll
users = repository.findFirst10ByLastnameOrderByFirstname("Doe", users.positionAt(users.size() - 1));
} while (!users.isEmpty() && users.hasNext());
|
上面的範例顯示了靜態排序和限制。您可以選擇性地定義接受 |
WindowIterator
提供了一個實用工具,透過移除檢查下一個 Window
是否存在以及應用 ScrollPosition
的需求,來簡化跨 Window
s 的捲動。
WindowIterator<User> users = WindowIterator.of(position -> repository.findFirst10ByLastnameOrderByFirstname("Doe", position))
.startingAt(ScrollPosition.offset());
while (users.hasNext()) {
User u = users.next();
// consume the user
}
使用偏移量捲動
偏移量捲動類似於分頁,使用偏移量計數器來跳過一些結果,並讓資料來源僅回傳從給定偏移量開始的結果。這種簡單的機制避免了將大型結果傳送到用戶端應用程式。然而,大多數資料庫需要具體化完整的查詢結果,伺服器才能回傳結果。
OffsetScrollPosition
與 Repository 查詢方法一起使用interface UserRepository extends Repository<User, Long> {
Window<User> findFirst10ByLastnameOrderByFirstname(String lastname, OffsetScrollPosition position);
}
WindowIterator<User> users = WindowIterator.of(position -> repository.findFirst10ByLastnameOrderByFirstname("Doe", position))
.startingAt(OffsetScrollPosition.initial()); (1)
1 | 從沒有偏移量開始,以包含位置 0 的元素。 |
|
使用鍵集過濾捲動
基於偏移量的方法要求大多數資料庫在伺服器可以回傳結果之前具體化整個結果。因此,雖然用戶端僅看到請求結果的一部分,但您的伺服器需要建構完整結果,這會造成額外負載。
鍵集過濾方法透過利用資料庫的內建功能來實現結果子集檢索,旨在減少個別查詢的計算和 I/O 需求。這種方法維護一組鍵,透過將鍵傳遞到查詢中來恢復捲動,有效地修改您的篩選條件。
鍵集過濾的核心思想是開始使用穩定的排序順序檢索結果。一旦您想要捲動到下一個區塊,您將取得一個 ScrollPosition
,用於重建排序結果內的位置。ScrollPosition
捕捉目前 Window
中最後一個實體的鍵集。為了執行查詢,重建會重寫條件子句以包含所有排序欄位和主鍵,以便資料庫可以利用潛在的索引來執行查詢。資料庫只需要從給定的鍵集位置建構一個小得多的結果,而無需完全具體化大型結果,然後跳過結果直到到達特定偏移量。
鍵集過濾要求鍵集屬性(用於排序的屬性)不可為空值。此限制的應用是由於商店特定的比較運算子空值處理,以及需要針對索引來源執行查詢。在可為空的屬性上進行鍵集過濾將導致意外的結果。 |
KeysetScrollPosition
與 Repository 查詢方法一起使用interface UserRepository extends Repository<User, Long> {
Window<User> findFirst10ByLastnameOrderByFirstname(String lastname, KeysetScrollPosition position);
}
WindowIterator<User> users = WindowIterator.of(position -> repository.findFirst10ByLastnameOrderByFirstname("Doe", position))
.startingAt(ScrollPosition.keyset()); (1)
1 | 從最開始處開始,並且不套用額外的篩選。 |
當您的資料庫包含與排序欄位匹配的索引時,鍵集過濾效果最佳,因此靜態排序效果良好。應用鍵集過濾的捲動查詢要求查詢回傳排序順序中使用的屬性,並且這些屬性必須對應到回傳的實體中。
您可以使用介面和 DTO 投影,但是請確保包含您已排序的所有屬性,以避免鍵集提取失敗。
在指定您的 Sort
順序時,包含與您的查詢相關的排序屬性就足夠了;如果您不想,則無需確保查詢結果是唯一的。鍵集查詢機制會透過包含主鍵(或複合主鍵的任何剩餘部分)來修改您的排序順序,以確保每個查詢結果都是唯一的。