Docs Menu
Docs Home
/ /

Tutorial: Paginar datos con Java y Quarkus

Este tutorial le muestra cómo implementar técnicas de paginación en una aplicación Quarkus conectada a MongoDB. Aprenderá a usar el repositorio de datos de Jakarta para crear puntos finales de la API REST compatibles con métodos de paginación basados ​​en desplazamiento y cursor.

La paginación es una técnica que se utiliza para dividir grandes conjuntos de datos en fragmentos más pequeños y manejables. Este tutorial implementa métodos de paginación basados ​​en desplazamiento y cursor. La paginación basada en desplazamiento utiliza números de página para recuperar subconjuntos específicos de datos, mientras que la paginación basada en cursor utiliza un punto de referencia, o un cursor, para navegar por el conjunto de datos.

Este tutorial muestra cómo realizar las siguientes acciones:

  • Verificar los prerrequisitos

  • Cree un proyecto de Quarkus con las dependencias necesarias

  • Configurar la conexión MongoDB

  • Definir una entidad de datos y un repositorio

  • Implementar puntos finales de API REST para paginación

  • Pruebe los puntos finales de paginación

1

Antes de comenzar, complete las siguientes tareas previas:

  • Instalar Java 21

  • Install Maven

  • Configurar un clúster de MongoDB, ya sea en MongoDB Atlas o en una instancia local de Docker

Para iniciar una instancia local de MongoDB con Docker, ejecute el siguiente comando:

docker run --rm -d --name mongodb-instance -p 27017:27017 mongo

Como alternativa, puede usar MongoDB Atlas e implementar un0 clúster M gratuito. Para aprender a crear una cuenta y un clúster de Atlas, consulte la guía de introducción a MongoDB.

2

Navegue hasta el generador de código Quarkus y configure su proyecto con las siguientes configuraciones:

  1. Seleccione su grupo preferido y el ID del artefacto.

  2. Agregue las siguientes dependencias:

    • Documento JNoSQL MongoDB (quarkus-jnosql-document-mongodb)

    • RESTEasy Reactivo (quarkus-resteasy-reactive)

    • RESTEasy Jackson reactivo (quarkus-resteasy-reactive-jackson)

    • API abierta (quarkus-smallrye-openapi)

  3. Genere el proyecto, descargue el archivo ZIP y extráigalo.

Nota

Si no puede encontrar una dependencia en el generador, agréguela manualmente al archivo pom.xml.

Después de completar la configuración, verifique que su archivo pom.xml incluya las siguientes dependencias:

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.jnosql</groupId>
<artifactId>quarkus-jnosql-document-mongodb</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3

Abra el archivo application.properties y agregue las siguientes propiedades de configuración para conectarse a su instancia de MongoDB:

quarkus.mongodb.connection-string = <your connection string>
jnosql.document.database = fruits

Esta configuración permite que su aplicación se conecte al clúster MongoDB en la cadena de conexión especificada y utilice la base de datos fruits.

Importante

En entornos de producción, habilite el control de acceso y aplique la autenticación. Para obtener más información, consulte la Lista de verificación de seguridad.

Puede anular estas propiedades mediante variables de entorno, que le permiten especificar diferentes configuraciones para el desarrollo, las pruebas y la producción sin modificar su código.

4

Cree una clase de entidad Fruit en el directorio src/main/java. El siguiente código define la entidad con los campos id y name:

import jakarta.nosql.Column;
import jakarta.nosql.Convert;
import jakarta.nosql.Entity;
import jakarta.nosql.Id;
import org.eclipse.jnosql.databases.mongodb.mapping.ObjectIdConverter;
@Entity
public class Fruit {
@Id
@Convert(ObjectIdConverter.class)
private String id;
@Column
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Fruit{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
public static Fruit of(String name) {
Fruit fruit = new Fruit();
fruit.setName(name);
return fruit;
}
}
5

Cree una interfaz FruitRepository que extienda la clase BasicRepository. El siguiente código define métodos para la paginación basada en desplazamiento y cursor:

import jakarta.data.Sort;
import jakarta.data.page.CursoredPage;
import jakarta.data.page.Page;
import jakarta.data.page.PageRequest;
import jakarta.data.repository.BasicRepository;
import jakarta.data.repository.Find;
import jakarta.data.repository.OrderBy;
import jakarta.data.repository.Repository;
@Repository
public interface FruitRepository extends BasicRepository<Fruit, String> {
@Find
CursoredPage<Fruit> cursor(PageRequest pageRequest, Sort<Fruit> order);
@Find
@OrderBy("name")
Page<Fruit> offSet(PageRequest pageRequest);
long countBy();
}

El marco implementa automáticamente esta interfaz, lo que le permite realizar operaciones de base de datos sin escribir código repetitivo.

6

Cree una clase SetupDatabase en el directorio src/main/java. El siguiente código llena la base de datos con datos de ejemplo al iniciar y los elimina al apagar:

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
import org.jboss.logging.Logger;
import java.util.List;
@ApplicationScoped
public class SetupDatabase {
private static final Logger LOGGER = Logger.getLogger(SetupDatabase.class.getName());
private final FruitRepository fruitRepository;
public SetupDatabase(FruitRepository fruitRepository) {
this.fruitRepository = fruitRepository;
}
void onStart(@Observes StartupEvent ev) {
LOGGER.info("The application is starting...");
long count = fruitRepository.countBy();
if (count > 0) {
LOGGER.info("Database already populated");
return;
}
List<Fruit> fruits = List.of(
Fruit.of("apple"),
Fruit.of("banana"),
Fruit.of("cherry"),
Fruit.of("date"),
Fruit.of("elderberry"),
Fruit.of("fig"),
Fruit.of("grape"),
Fruit.of("honeydew"),
Fruit.of("kiwi"),
Fruit.of("lemon")
);
fruitRepository.saveAll(fruits);
}
void onStop(@Observes ShutdownEvent ev) {
LOGGER.info("The application is stopping...");
fruitRepository.deleteAll(fruitRepository.findAll().toList());
}
}
7

Cree una clase FruitResource en el directorio src/main/java. Luego, pegue el siguiente código en el archivo de clase:

import jakarta.data.Sort;
import jakarta.data.page.PageRequest;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
@Path("/fruits")
public class FruitResource {
private final FruitRepository fruitRepository;
private static final Sort<Fruit> ASC = Sort.asc("name");
private static final Sort<Fruit> DESC = Sort.desc("name");
public FruitResource(FruitRepository fruitRepository) {
this.fruitRepository = fruitRepository;
}
@Path("/offset")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Iterable<Fruit> offset(@QueryParam("page") @DefaultValue("1") long page,
@QueryParam("size") @DefaultValue("2") int size) {
var pageRequest = PageRequest.ofPage(page).size(size);
return fruitRepository.offSet(pageRequest).content();
}
@Path("/cursor")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Iterable<Fruit> cursor(@QueryParam("after") @DefaultValue("") String after,
@QueryParam("before") @DefaultValue("") String before,
@QueryParam("size") @DefaultValue("2") int size) {
if (!after.isBlank()) {
var pageRequest = PageRequest.ofSize(size).afterCursor(PageRequest.Cursor.forKey(after));
return fruitRepository.cursor(pageRequest, ASC).content();
} else if (!before.isBlank()) {
var pageRequest = PageRequest.ofSize(size).beforeCursor(PageRequest.Cursor.forKey(before));
return fruitRepository.cursor(pageRequest, DESC).stream().toList();
}
var pageRequest = PageRequest.ofSize(size);
return fruitRepository.cursor(pageRequest, ASC).content();
}
}

Esta clase define los siguientes puntos finales:

  • /fruits/offset:Admite paginación basada en desplazamiento mediante el parámetro de consulta page.

  • /fruits/cursor:Admite paginación basada en cursor mediante el uso de los parámetros de consulta after y before.

Ambos puntos finales también aceptan el parámetro de consulta size para especificar la cantidad de elementos por página.

8

Ejecute el siguiente comando desde el directorio de su proyecto para iniciar su aplicación Quarkus en modo de desarrollo:

./mvnw compile quarkus:dev
9

En una ventana de terminal independiente, use los siguientes comandos curl para probar el punto final de paginación de desplazamiento. Estos comandos solicitan diferentes páginas de datos de fruta.

Para obtener la primera página, ejecute el siguiente comando:

curl --location http://localhost:8080/fruits/offset?page=1

Para obtener la segunda página, ejecute el siguiente comando:

curl --location http://localhost:8080/fruits/offset?page=2

Para obtener la quinta página, ejecute el siguiente comando:

curl --location http://localhost:8080/fruits/offset?page=5
10

Utilice los siguientes comandos curl para probar el punto final de paginación del cursor. Estos comandos utilizan los parámetros after y before para navegar por el conjunto de datos.

Para obtener el conjunto inicial de frutas, ejecute el siguiente comando:

curl --location http://localhost:8080/fruits/cursor

Para obtener frutas con valores de campo name que vienen después de "banana", ejecute el siguiente comando:

curl --location http://localhost:8080/fruits/cursor?after=banana

Para obtener frutas con valores de campo name que vienen antes de "date", ejecute el siguiente comando:

curl --location http://localhost:8080/fruits/cursor?before=date

Para obtener más información sobre la paginación en MongoDB, consulte la guía Paginar resultados en la documentación de MongoDB Atlas.

Para obtener más información sobre Quarkus, consulte la documentación de Quarkus.

Volver

Quarkus con Panache y MongoDB

En esta página