importcom.google.appengine.api.datastore.Cursor;importcom.google.appengine.api.datastore.DatastoreService;importcom.google.appengine.api.datastore.DatastoreServiceFactory;importcom.google.appengine.api.datastore.Entity;importcom.google.appengine.api.datastore.FetchOptions;importcom.google.appengine.api.datastore.PreparedQuery;importcom.google.appengine.api.datastore.Query;importcom.google.appengine.api.datastore.Query.SortDirection;importcom.google.appengine.api.datastore.QueryResultList;importjava.io.IOException;importjava.io.PrintWriter;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;publicclassListPeopleServletextendsHttpServlet{staticfinalintPAGE_SIZE=15;privatefinalDatastoreServicedatastore;publicListPeopleServlet(){datastore=DatastoreServiceFactory.getDatastoreService();}@OverrideprotectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{FetchOptionsfetchOptions=FetchOptions.Builder.withLimit(PAGE_SIZE);// If this servlet is passed a cursor parameter, let's use it.StringstartCursor=req.getParameter("cursor");if(startCursor!=null){fetchOptions.startCursor(Cursor.fromWebSafeString(startCursor));}Queryq=newQuery("Person").addSort("name",SortDirection.ASCENDING);PreparedQuerypq=datastore.prepare(q);QueryResultList<Entity>results;try{results=pq.asQueryResultList(fetchOptions);}catch(IllegalArgumentExceptione){// IllegalArgumentException happens when an invalid cursor is used.// A user could have manually entered a bad cursor in the URL or there// may have been an internal implementation detail change in App Engine.// Redirect to the page without the cursor parameter to show something// rather than an error.resp.sendRedirect("/people");return;}resp.setContentType("text/html");resp.setCharacterEncoding("UTF-8");PrintWriterw=resp.getWriter();w.println("<!DOCTYPE html>");w.println("<meta charset=\"utf-8\">");w.println("<title>Cloud Datastore Cursor Sample</title>");w.println("<ul>");for(Entityentity:results){w.println("<li>"+entity.getProperty("name")+"</li>");}w.println("</ul>");StringcursorString=results.getCursor().toWebSafeString();// This servlet lives at '/people'.w.println("<a href='/people?cursor="+cursorString+"'>Next page</a>");}}
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["難以理解","hardToUnderstand","thumb-down"],["資訊或程式碼範例有誤","incorrectInformationOrSampleCode","thumb-down"],["缺少我需要的資訊/範例","missingTheInformationSamplesINeed","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-08-19 (世界標準時間)。"],[[["\u003cp\u003eThis API supports first-generation runtimes and can be used when upgrading to corresponding second-generation runtimes, with a migration guide available for App Engine Java 11/17 users.\u003c/p\u003e\n"],["\u003cp\u003eQuery cursors are recommended over integer offsets for pagination, allowing applications to retrieve query results in batches without the overhead of a query offset.\u003c/p\u003e\n"],["\u003cp\u003eCursors are opaque base64-encoded strings marking the index position of the last retrieved result, enabling applications to save and use them for subsequent retrievals.\u003c/p\u003e\n"],["\u003cp\u003eUnlike offsets, using cursors avoids the cost of retrieving and processing skipped entities, as these entities are still retrieved internally when offsets are used.\u003c/p\u003e\n"],["\u003cp\u003eCursors have limitations, including the requirement to use the exact same query, restrictions with certain operators, and potential invalidation due to App Engine updates, which could raise errors.\u003c/p\u003e\n"]]],[],null,[]]