Overview
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.
Paginación
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.
Tutorial
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
Verificar los prerrequisitos.
Antes de comenzar, complete las siguientes tareas previas:
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.
Crear un proyecto de Quarkus.
Navegue hasta el generador de código Quarkus y configure su proyecto con las siguientes configuraciones:
Seleccione su grupo preferido y el ID del artefacto.
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)
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>
Configurar la base de datos MongoDB.
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.
Crear una entidad de datos.
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; public class Fruit { private String id; 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; } public String toString() { return "Fruit{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; } public static Fruit of(String name) { Fruit fruit = new Fruit(); fruit.setName(name); return fruit; } }
Crear una interfaz de repositorio.
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; public interface FruitRepository extends BasicRepository<Fruit, String> { CursoredPage<Fruit> cursor(PageRequest pageRequest, Sort<Fruit> order); 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.
Crear una clase de configuración de base de datos.
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; 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( 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( ShutdownEvent ev) { LOGGER.info("The application is stopping..."); fruitRepository.deleteAll(fruitRepository.findAll().toList()); } }
Crear puntos finales de API REST.
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; 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; } public Iterable<Fruit> offset( long page, int size) { var pageRequest = PageRequest.ofPage(page).size(size); return fruitRepository.offSet(pageRequest).content(); } public Iterable<Fruit> cursor( String after, String before, 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 consultapage./fruits/cursor:Admite paginación basada en cursor mediante el uso de los parámetros de consultaafterybefore.
Ambos puntos finales también aceptan el parámetro de consulta size para especificar la cantidad de elementos por página.
Pruebe la paginación basada en desplazamiento.
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
Pruebe la paginación basada en el cursor.
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
Recursos adicionales
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.