Mybatis Interceptor 拦截器是Mybatis框架使用的一种插件机制,可以拦截Sql语句执行的过程,对Sql进行加工或者做其他处理,比如增加动态SQL条件、查询性能优化等。以下是Mybatis Interceptor 拦截器的完整实现攻略:
Mybatis Interceptor 拦截器的实现步骤
步骤1:定义自定义Interceptor类
实现Mybatis提供的org.apache.ibatis.plugin.Interceptor接口,该接口有3个方法需要实现:
- intercept:拦截方法的执行
- plugin:用来生成目标对象的绑定代理
- setProperties:在插件配置中设置属性
步骤2:定义需要拦截的目标对象和拦截点
定义需要拦截的目标对象,例如Executor、ParameterHandler、ResultSetHandler、StatementHandler等。使用Mybatis提供的注解@Intercepts注解来指定拦截点,拦截点可以是目标对象的具体方法,也可以是目标对象的所有方法。
步骤3:在Mybatis配置文件中配置Interceptor
在Mybatis配置文件中,使用
示例1:实现自定义Sql查询拦截器
假设有如下需求:项目中所有查询语句,都需要添加一条限制条件,只查询age>18的数据。实现该需求可以使用Mybatis Interceptor拦截器,在执行查询语句前,将其动态修改为指定的查询条件。
以下是完整代码:
@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class})})
public class CustomSqlInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
if (!mappedStatement.getId().matches(".+\\.select.+")) {
// 非查询操作跳过
return invocation.proceed();
}
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();
if (StringUtils.isBlank(sql)) {
return invocation.proceed();
}
String querySql = sql.concat(" WHERE age > 18");
metaObject.setValue("delegate.boundSql.sql", querySql);
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
解释:
- 在该示例中,我们定义了一个名为CustomSqlInterceptor的自定义拦截器,实现了Mybatis提供的Interceptor接口。
- 通过@Intercepts注解指定要拦截的方法签名,该示例中仅拦截查询类型的StatementHandler。
- 在intercept方法中,判断是否为查询类型的SQL语句,如果是,则为其添加限制条件“WHERE age > 18”。
- 最后将修改后的Sql语句返回并执行。
示例2:实现自定义分页拦截器
假设有如下需求:在项目中使用分页查询时,对查询的记录条数进行限制,每次查询最多返回100条记录。为了实现该需求,我们可以自定义一个Mybatis拦截器,拦截所有的查询操作,将其转换为分页查询,并进行记录限制。
以下是完整代码:
@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class})})
public class PageInterceptor implements Interceptor {
private static int PAGE_SIZE = 100;
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
// 检查是否为分页操作
Page<?> page = PageContextHolder.getPageContext();
if (Objects.isNull(page) || !mappedStatement.getId().matches(page.getStatementRegexp())) {
return invocation.proceed();
}
// 分页拦截
BoundSql boundSql = statementHandler.getBoundSql();
String querySql = boundSql.getSql();
querySql = querySql.trim().toLowerCase();
int start = page.getPageNum();
int limit = PAGE_SIZE;
if (start > 1) {
start = (start - 1) * PAGE_SIZE + 1;
}
int end = start + limit - 1;
String pageSql = "SELECT * FROM(SELECT tmp.*,rownum rn FROM ( " + querySql +
" ) tmp WHERE rownum <= "+ end +") WHERE rn >= " + start;
metaObject.setValue("delegate.boundSql.sql", pageSql);
// 总数统计拦截
Connection conn = (Connection) invocation.getArgs()[0];
PreparedStatement countStmt = null;
ResultSet rs = null;
try {
String countSql = "SELECT COUNT(1) FROM (" + querySql + ")";
countStmt = conn.prepareStatement(countSql);
rs = countStmt.executeQuery();
int totalCount = 0;
if (rs.next()) {
totalCount = rs.getInt(1);
}
page.setTotalCount(totalCount);
} finally {
rs.close();
countStmt.close();
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
解释:
- 在该示例中,我们定义了一个名为PageInterceptor的自定义拦截器,实现了Mybatis提供的Interceptor接口。
- 通过@Intercepts注解指定要拦截的方法签名,该示例中仅拦截查询类型的StatementHandler。
- 在intercept方法中,首先检查是否有分页数据存在,如果有则进行分页拦截。
- 接着,通过获取总数的SQL,统计总的记录条数并进行限制。
- 最后将修改后的Sql语句返回并执行。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Mybatis Interceptor 拦截器的实现 - Python技术站