MyBatis-Plus
在使用多租户功能时、有些接口、我们并不想被多租户过滤、这个时候就用到了 SqlParserFilter
sql解析过滤器
看了 MyBatis-Plus
一部分源码后得知、该过滤器的大致功能方向、以及用法
首先是配置 PaginationInterceptor
类、官方示例查看 多租户解析 PaginationInterceptor
继承 AbstractSqlParserHandler
类、解析最重要的方法就在 AbstractSqlParserHandler
类的sqlParser方法中
protected void sqlParser(MetaObject metaObject) {
if (null != metaObject) {
Object originalObject = metaObject.getOriginalObject();
StatementHandler statementHandler = (StatementHandler)PluginUtils.realTarget(originalObject);
metaObject = SystemMetaObject.forObject(statementHandler);
//1、这一句就是SqlParserFilter的作用、如果SqlParserFilter不等于空、并且执行SqlParserFilter接口的doFilter
// 方法的到的结果值为 true 的话就不往下执行了
if (null != this.sqlParserFilter && this.sqlParserFilter.doFilter(metaObject)) {
return;
}
//2、这个是用于@SqlParser注解的、如果@SqlParser注解值为 true 则不往下执行、这个是放在Mapper接口上的
if (SqlParserHelper.getSqlParserInfo(metaObject)) {
return;
}
//3、这里开始进行SQL解析 sqlParserList是解析链
if (CollectionUtils.isNotEmpty(this.sqlParserList)) {
statementHandler = metaObject.hasGetter("delegate") ? (StatementHandler)metaObject.getValue("delegate") : statementHandler;
if (!(statementHandler instanceof CallableStatementHandler)) {
boolean sqlChangedFlag = false; //标记是否修改过Sql
String originalSql = (String)metaObject.getValue("delegate.boundSql.sql");
Iterator var6 = this.sqlParserList.iterator();
//循环解析了
while(var6.hasNext()) {
ISqlParser sqlParser = (ISqlParser)var6.next();
if (sqlParser.doFilter(metaObject, originalSql)) {
SqlInfo sqlInfo = sqlParser.parser(metaObject, originalSql);
if (null != sqlInfo) {
originalSql = sqlInfo.getSql();
sqlChangedFlag = true;
}
}
}
if (sqlChangedFlag) {
metaObject.setValue("delegate.boundSql.sql", originalSql);
}
}
}
}
}
大概原理也就和上面的类似、如果有兴趣还可以把多租户的TenantSqlParser
扩展一下、扩展成只拦截删除标识
的、这样也可以做到全局的删除标识
自动追加、不过有点遗憾的就是 SqlParserFilter
是统一设置过滤的、并不是根据一个个的 SqlParser
进行有规范的过滤、当然TenantSqlParser
也是有自己的处理规范的、但是如果改写 TenantSqlParser
后两个处理规范多多少少会冲突、有些接口是注定需要手动追加的,可参考 MyBatis-Plus根据多租户扩展删除标识功能
注意点 SqlParserFilter的doFilter方法中,如果使用MetaObject类的getId方法去判断该方法是过滤还是放行的时候、对比的方法必须是Mapper方法,因为MetaObject的getId方法得到的都是Mapper层的方法