要实现全局 select 语句的 limit 限制,可以通过配置 SQL 拦截器来拦截所有的 SELECT 语句,然后在拦截器中添加 LIMIT 条件。具体实现步骤如下:
- 创建一个实现了 org.apache.ibatis.plugin.Interceptor 接口的拦截器类。
- 在拦截器类中实现方法 intercept,该方法会在执行 SQL 语句时被调用,可以在该方法中对 SQL 语句进行修改。
- 在拦截器类上添加注解 @Intercepts,指定要拦截的 SQL 方法和类型,例如:@Intercepts({@Signature(type=StatementHandler.class, method="prepare", args={Connection.class, Integer.class})})。
- 在方法 intercept 中获取到 SQL 语句,并在末尾添加 LIMIT 条件。
代码如下
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.Properties;
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class LimitInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();
// 是 select 语句 且 不包含LIMIT参数时
if (sql.trim().toLowerCase().startsWith("select") && !sql.contains("LIMIT") && !sql.contains("limit")) {
// 添加 LIMIT 条件,默认查询语句最多查询 5000 条记录
sql += String.format(" LIMIT %s",5000);
// 反射修改 BoundSql 中的 SQL 语句
Field field = boundSql.getClass().getDeclaredField("sql");
field.setAccessible(true);
field.set(boundSql, sql);
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Interceptor.super.plugin(target);
}
@Override
public void setProperties(Properties properties) {
Interceptor.super.setProperties(properties);
}
}
默认 limit 效果(自动加上 limit 5000 限制)
pagehelper 自带 limit 效果(使用 pagehelper 参数,不修改 sql 参数直接放行)