Existen diversas estrategias para implementar paginación en aplicaciones que utilizan MyBatis. A continuación, se detallan los enfoques más comunes, desde soluciones manuales hasta el uso de plugins especializados.
1. Inyección manual de parámetros en SQL
La forma más directa consiste en pasar los parámetros de desplazamiento (offset) y límite (limit) directamente a la sentencia SQL. Esta técnica es simple pero requiere calcular el índice inicial en la capa de lógica de negocio.
<select id="fetchRecordsPaginated" parameterType="map" resultMap="entityMap">
SELECT * FROM my_table LIMIT #{offset}, #{limit}
</select>
// Lógica en el servicio
public List<Entity> getItems(int page, int size) {
Map<String, Object> params = new HashMap<>();
params.put("offset", (page - 1) * size);
params.put("limit", size);
return mapper.fetchRecordsPaginated(params);
}
2. Uso de RowBounds
MyBatis provee la clase RowBounds para manejar la paginación de memoria a nivel de capa de abstracción. Aunque es sencilllo, debe usarse con precaución en conjuntos de datos masivos, ya que puede cargar más registros de los deseados en la memoria de la JVM antes de filtrar.
// Interfaz del Mapper
List<User> findUsers(RowBounds bounds);
// Uso en Servicio
public List<User> getPaginatedUsers(int offset, int limit) {
return userMapper.findUsers(new RowBounds(offset, limit));
}
3. Dsearrollo de un Interceptor personalizado
Para un control total, es posible implementar la interfaz Interceptor de MyBatis. Esto permite interceptar la ejecución de los comandos SQL y modificar dinámicamente la consulta antes de que sea enviada a la base de datos.
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class CustomPaginationInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler handler = (StatementHandler) invocation.getTarget();
MetaObject metaObject = SystemMetaObject.forObject(handler);
// Lógica para extraer la consulta original y añadir el LIMIT
String originalSql = (String) metaObject.getValue("delegate.boundSql.sql");
String modifiedSql = originalSql + " LIMIT ?, ?";
metaObject.setValue("delegate.boundSql.sql", modifiedSql);
return invocation.proceed();
}
}
Para activar este interceptor, debe registrarse en la configuración global de MyBatis dentro del bloque <plugins>.
4. Uso del plugin PageHelper
PageHelper es la solución estándar de la industria. Automatiza la paginación mediante un enterceptor altamente optimizado que añade automáticamente las cláusulas de paginación según el dialecto de la base de datos.
// Dependencia en Maven
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.0</version>
</dependency>
Su uso es transparente, ya que solo requiere invocar PageHelper.startPage justo antes de ejecutar la consulta deseada:
PageHelper.startPage(1, 10);
List<User> list = userMapper.findAll(); // La consulta se pagina automáticamente