In addition to using a Where
clause to limit the number of entities returned, there are a couple of other approaches possible. This recipe addresses the use of methods to control the number of entities returned and to specify the first entity of the set to return. This permits us to retrieve the results of a query as a series of subsets.
This technique is useful when we want to display only a subset of entities at a time. By displaying a partial set, the user is not overwhelmed with a long list and a partial list will be returned faster than a complete list.
We will execute a query in the same way as before, but limit the number returned using a combination of Query
methods. If only one entity is needed then the getSingleResult
method can be used.
If subsets are needed, then the getResultList
method can be used in conjunction with the setMaxResults
and setFirstResult
methods. The steps used for this approach include:
To illustrate this technique, add a method called processAllPatients
to the PatientFacade
class. In this method we will create a query to return all of the entities in the corresponding table. We will then use the setMaxResults
method to restrict the number of entities returned and the setFirstResult
to specify the first entity to be returned. The resulting list is then used to display the patient's name.
public void processAllPatients(PrintWriter out) { int querySize = 5; int beginIndex = 0; while(true) { Query query = entityManager.createQuery("SELECT p FROM Patient p"); query.setMaxResults(querySize); query.setFirstResult(beginIndex); List<Patient> list = query.getResultList(); // Process list if (list.isEmpty()) { break; } else { // Process for (Patient patient : list) { out.println("<h5>"+patient.getFirstName()+"</h5>"); } entityManager.clear(); beginIndex = beginIndex + list.size(); } } } }
Add a call to the method in the PatientServlet
after the body tag is displayed.
... out.println("<body>"); patientFacade.processAllPatients(out);
Execute the PatientServlet
and you should get the output as illustrated in the following screenshot:
The query used will normally return all of the elements from the patient table. However, the setMaxResults
was set to querySize
restricting the number of entities actually returned. In this example it was set to 5. The setFirstResult
method determined the index of the first entity of the larger result set to return. The query was then executed using the getResultList
method.
If the list is empty then the loop is terminated with the break
statement. This will happen when all of the entities have been returned.
The processing simply displayed the first name of each entity returned. After the processing was complete, the clear
method was executed to detach the objects processed so far. This resulted in a more efficient retrieval of the entities. Next, the beginIndex
was incremented by the size of the list. During subsequent iterations of the loop, different sets of entities will be retrieved.
Instead of retrieving several entities at a time, it is possible to return a single entity at a time. If you know the query will return a single entity, it is more efficient to use the getSingleResult
method.
Query query = entityManager.createQuery("..."); number of entitiesgetSingleResult methodPatient patient = query.getSingleResult();
The getSingleResult
method will throw an EntityNotFoundException
if it is unsuccessful.
We can also limit the number of entities returned to one using the setMaxResults
method. We can achieve the same result using a value of one.
query.setMaxResults(1);
18.223.196.146