簡體   English   中英

如何使用游標實現休眠分頁(即使將新數據添加到要分頁的表中,結果也保持一致)?

[英]How do I implement Hibernate Pagination using a cursor (so the results stay consistent, despite new data being added to the table being paged)?

有什么方法可以在Web請求之間使用Hibernate維護數據庫游標嗎? 基本上,我正在嘗試實現分頁,但是正在分頁的數據一直在變化(即,將新記錄添加到數據庫中)。 我們正在嘗試對其進行設置,以便在您進行初始搜索(最多返回5000個結果)並在結果中進行分頁時,這些相同的記錄始終出現在同一頁上(即,我們不會連續運行查詢)每次單擊下一頁和上一頁按鈕)。 我們當前實現此方法的方式是,僅從要分頁的表中選擇5000個(最多)主鍵,將這些鍵存儲在內存中,然后一次僅使用20個主鍵從數據庫中獲取其詳細信息。 但是,我們希望擺脫必須將這些鍵存儲在內存中的情況,而更希望使用數據庫游標,因為我們只需不斷地在該游標上來回移動,以生成頁面。

我嘗試使用Hibernate的ScrollableResults進行此操作,但發現如果您在其他Web請求/ Hibernate會話中,則無法調用next()和previous()之類的方法會導致異常(這並不奇怪)。 有沒有什么方法可以將ScrollableResults對象重新附加到Session,與重新附加一個分離的數據庫對象使其持久化的方法幾乎相同? 是否有其他方法可以在不緩存主鍵的情況下以一致的分頁結果實現此數據分頁?

本質上,您是自己一個人做的。 您要做的就是看一下OpenSessionInView過濾器並構建自己的過濾器,這樣就不必為每個請求創建一個新的HibernateSession,而是從與用戶的Web會話關聯的緩存中提取一個。

如果您沒有像Spring WebFlow這樣的框架為您提供一些對話結構,那么您也將需要構建該框架。 因為除了“ Web會話到期時”之外,您可能還需要某種方法來管理Hibernate會話的生命周期。 您也很可能不希望來自同一Web會話的兩個用戶線程,但希望共享休眠會話的不同瀏覽器選項卡。 (很可能隨之而來。)

永遠不要使用offset,因為offset還會讀取offset之前的所有數據,這非常低效。

您需要按索引的唯一屬性排序,並在API調用中返回最后一項屬性的值,並使用WHERE子句從離開的地方開始。 最后一項的屬性值將是您的光標位置。 例如,使用主鍵id作為游標的簡單分頁查詢將如下所示:

List<MyEntity> entities = entityManager
    .createQuery("""
        FROM
            MyEntity e
        WHERE
            e.id > :cursorPosition
        ORDER BY
            e.id ASC
    """, MyEntity.class)
    .setParameter("cursorPosition", cursorPosition)
    .setMaxResults(pageSize)
    .getResultList()

對API的第一次調用, cursorPosition值可以為0。第二次您將從客戶端收到的客戶端從第一次調用中收到的游標。 了解Google Maps分頁的地點查詢如何與nextPageToken屬性一起使用。

您的光標必須是一個字符串,用於標識查詢的所有參數。 因此,如果您有其他參數,則必須使用游標才能檢索到。

我相信您可以通過多種方式做到這一點。 一種方法是將所有參數和cursorPosition連接在字符串中,將其編碼為URL友好的字符串(例如Base64),然后在接收回解碼時將其拆分為原始參數:

 String nextPageToken = Base64.getUrlEncoder()
     .encodeToString("indexProperty=id&cursorPos=123&ageBiggerThan=65".getBytes())

您的api調用將返回如下的json:

{
    "items": [ ... ],
    "nextPageToken": "aW5kZXhQcm9wZXJ0eT1pZCZjdXJzb3JQb3M9MTIzJmFnZUJpZ2dlclRoYW49NjU="
}

然后客戶端下一個電話:

GET https://www.example.com/api/myservice/v1/myentity?pageToken=aW5kZXhQcm9wZXJ0eT1pZCZjdXJzb3JQb3M9MTIzJmFnZUJpZ2dlclRoYW49NjU=

連接和拆分游標字符串的部分可能很煩人,我真的不知道是否有一個庫來處理創建令牌和解析它的工作,我實際上在這個問題中,因為我一直在尋找它。 但是我的猜測是GSON或Jackson可以為您節省代碼行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM