オフセットはオフセットの前のすべてのデータも読み取るため、オフセットは使用しないでください。これは非常に非効率的です。
インデックス付きの一意のプロパティで並べ替え、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 にすることができます。2 番目の呼び出しでは、クライアントが最初の呼び出しで受け取ったカーソルをクライアントから受け取ります。Google マップのページ分割された場所のクエリがnextPageToken
属性でどのように機能するかをご覧ください。
カーソルは、クエリのすべてのパラメーターを識別する文字列である必要があります。したがって、追加のパラメーターがある場合は、カーソルで取得できる必要があります。
これは複数の方法で実行できると思います。1 つの方法は、すべてのパラメーターを連結cursorPosition
し、文字列で Base64 などの URL フレンドリーな文字列にエンコードし、受信時にデコードして元のパラメーターに分割することです。
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 を使用すると、これに関するコード行を節約できると思います。