在将项目改成多租户模式时,因为mybatis-plus自带的功能只会拼接left 、from和where后面的表或子查询添加租户id。想要将selete部分的子查询拼接租户id,必须重写TenantSqlParser类的processPlainSelect(PlainSelect plainSelect)方法,代码如下:
public class TestTenantSqlParser extends TenantSqlParser {
@Override
protected void processPlainSelect(PlainSelect plainSelect) {
// SELECT 至 FROM 中的嵌套查询
List<SelectItem> selectItemList = plainSelect.getSelectItems();
for (SelectItem selectItem : selectItemList) {
if (selectItem instanceof SelectExpressionItem) {
SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
if (!(selectExpressionItem.getExpression() instanceof Column)) {
// 处理 column select 嵌套部分
operateExpression(selectExpressionItem.getExpression());
}
}
}
processPlainSelect(plainSelect, false);
}
private void operateExpression(Expression expression){
if (expression instanceof SubSelect){
SubSelect subSelect = (SubSelect) expression;
PlainSelect plainSelect = (PlainSelect) subSelect.getSelectBody();
processSelectBody(plainSelect);
}
else if (expression instanceof Parenthesis){
Parenthesis parenthesis= (Parenthesis) expression;
operateExpression(parenthesis.getExpression());
}else if (expression instanceof CaseExpression) { //处理case when
CaseExpression caseExpression= (CaseExpression) expression;
caseExpression.getWhenClauses();
List<Expression> whenClauses = caseExpression.getWhenClauses();
for (Expression e : whenClauses) {
if (e instanceof WhenClause){
WhenClause whenClause= (WhenClause) e;
operateExpression(whenClause.getThenExpression());
}
}
}else if (expression instanceof Function){//处理IFNULL
Function function= (Function) expression;
if ("IFNULL".equals(function.getName())){
ExpressionList expressionList=function.getParameters();
List<Expression> ifExpression=expressionList.getExpressions();
for (Expression e:ifExpression){
operateExpression(e);
}
}
}
}
}
然后在配置文件调用
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
paginationInterceptor.setLocalPage(true);// 开启 PageHelper 的支持
/*
* 【测试多租户】 SQL 解析处理拦截器<br>
* 这里固定写成住户 1 实际情况你可以从cookie读取,因此数据看不到 【 麻花藤 】 这条记录( 注意观察 SQL )<br>
*/
List<ISqlParser> sqlParserList = new ArrayList<>();
/**
*此处调用重写的类
*
*/
TestTenantSqlParser tenantSqlParser = new TestTenantSqlParser ();
tenantSqlParser.setTenantHandler(new TenantHandler() {
@Override
public Expression getTenantId() {
return new LongValue(1L);
}
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public boolean doTableFilter(String tableName) {
// 这里可以判断是否过滤表
/*
if ("user".equals(tableName)) {
return true;
}*/
return false;
}
});
sqlParserList.add(tenantSqlParser);
paginationInterceptor.setSqlParserList(sqlParserList);
paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {
@Override
public boolean doFilter(MetaObject metaObject) {
MappedStatement ms = PluginUtils.getMappedStatement(metaObject);
// 过滤自定义查询此时无租户信息约束【 麻花藤 】出现
if ("com.baomidou.springboot.mapper.UserMapper.selectListBySQL".equals(ms.getId())) {
return true;
}
return false;
}
});
return paginationInterceptor;
}