All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser Maven / Gradle / Ivy

There is a newer version: 3.5.7
Show newest version
/*
 * Copyright (c) 2011-2020, hubin ([email protected]).
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.baomidou.mybatisplus.extension.plugins.tenant; import java.util.List; import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; import com.baomidou.mybatisplus.core.parser.AbstractJsqlParser; import net.sf.jsqlparser.expression.BinaryExpression; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.ItemsList; import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.delete.Delete; import net.sf.jsqlparser.statement.insert.Insert; import net.sf.jsqlparser.statement.select.FromItem; import net.sf.jsqlparser.statement.select.Join; import net.sf.jsqlparser.statement.select.LateralSubSelect; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.SelectBody; import net.sf.jsqlparser.statement.select.SelectExpressionItem; import net.sf.jsqlparser.statement.select.SetOperationList; import net.sf.jsqlparser.statement.select.SubJoin; import net.sf.jsqlparser.statement.select.SubSelect; import net.sf.jsqlparser.statement.select.ValuesList; import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.update.Update; /** *

* 租户 SQL 解析器( TenantId 行级 ) *

* * @author hubin * @since 2017-09-01 */ public class TenantSqlParser extends AbstractJsqlParser { private TenantHandler tenantHandler; /** * select 语句处理 */ @Override public void processSelectBody(SelectBody selectBody) { if (selectBody instanceof PlainSelect) { processPlainSelect((PlainSelect) selectBody); } else if (selectBody instanceof WithItem) { WithItem withItem = (WithItem) selectBody; if (withItem.getSelectBody() != null) { processSelectBody(withItem.getSelectBody()); } } else { SetOperationList operationList = (SetOperationList) selectBody; if (operationList.getSelects() != null && operationList.getSelects().size() > 0) { operationList.getSelects().forEach(this::processSelectBody); } } } /** *

* insert 语句处理 *

*/ @Override public void processInsert(Insert insert) { if (this.tenantHandler.doTableFilter(insert.getTable().getName())) { // 过滤退出执行 return; } insert.getColumns().add(new Column(this.tenantHandler.getTenantIdColumn())); if (insert.getSelect() != null) { processPlainSelect((PlainSelect) insert.getSelect().getSelectBody(), true); } else if (insert.getItemsList() != null) { // fixed github pull/295 ItemsList itemsList = insert.getItemsList(); if (itemsList instanceof MultiExpressionList) { ((MultiExpressionList) itemsList).getExprList().forEach(el -> el.getExpressions().add(tenantHandler.getTenantId())); } else { ((ExpressionList) insert.getItemsList()).getExpressions().add(tenantHandler.getTenantId()); } } else { throw new MybatisPlusException("Failed to process multiple-table update, please exclude the tableName or statementId"); } } /** *

* update 语句处理 *

*/ @Override public void processUpdate(Update update) { List tableList = update.getTables(); if (null == tableList || tableList.size() >= 2) { throw new MybatisPlusException("Failed to process multiple-table update, please exclude the statementId"); } Table table = tableList.get(0); if (this.tenantHandler.doTableFilter(table.getName())) { // 过滤退出执行 return; } update.setWhere(this.andExpression(table, update.getWhere())); } /** *

* delete 语句处理 *

*/ @Override public void processDelete(Delete delete) { if (this.tenantHandler.doTableFilter(delete.getTable().getName())) { // 过滤退出执行 return; } delete.setWhere(this.andExpression(delete.getTable(), delete.getWhere())); } /** *

* delete update 语句 where 处理 *

*/ protected BinaryExpression andExpression(Table table, Expression where) { //获得where条件表达式 EqualsTo equalsTo = new EqualsTo(); equalsTo.setLeftExpression(this.getAliasColumn(table)); equalsTo.setRightExpression(tenantHandler.getTenantId()); if (null != where) { return new AndExpression(equalsTo, where); } return equalsTo; } /** *

* 处理 PlainSelect *

*/ protected void processPlainSelect(PlainSelect plainSelect) { processPlainSelect(plainSelect, false); } /** *

* 处理 PlainSelect *

* * @param plainSelect * @param addColumn 是否添加租户列,insert into select语句中需要 */ protected void processPlainSelect(PlainSelect plainSelect, boolean addColumn) { FromItem fromItem = plainSelect.getFromItem(); if (fromItem instanceof Table) { Table fromTable = (Table) fromItem; if (this.tenantHandler.doTableFilter(fromTable.getName())) { // 过滤退出执行 return; } plainSelect.setWhere(builderExpression(plainSelect.getWhere(), fromTable)); if (addColumn) { plainSelect.getSelectItems().add(new SelectExpressionItem(new Column(this.tenantHandler.getTenantIdColumn()))); } } else { processFromItem(fromItem); } List joins = plainSelect.getJoins(); if (joins != null && joins.size() > 0) { joins.forEach(j -> { processJoin(j); processFromItem(j.getRightItem()); }); } } /** * 处理子查询等 */ protected void processFromItem(FromItem fromItem) { if (fromItem instanceof SubJoin) { SubJoin subJoin = (SubJoin) fromItem; if (subJoin.getJoinList() != null) { subJoin.getJoinList().forEach(j -> processJoin(j)); } if (subJoin.getLeft() != null) { processFromItem(subJoin.getLeft()); } } else if (fromItem instanceof SubSelect) { SubSelect subSelect = (SubSelect) fromItem; if (subSelect.getSelectBody() != null) { processSelectBody(subSelect.getSelectBody()); } } else if (fromItem instanceof ValuesList) { logger.debug("Perform a subquery, if you do not give us feedback"); } else if (fromItem instanceof LateralSubSelect) { LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem; if (lateralSubSelect.getSubSelect() != null) { SubSelect subSelect = lateralSubSelect.getSubSelect(); if (subSelect.getSelectBody() != null) { processSelectBody(subSelect.getSelectBody()); } } } } /** * 处理联接语句 */ protected void processJoin(Join join) { if (join.getRightItem() instanceof Table) { Table fromTable = (Table) join.getRightItem(); if (this.tenantHandler.doTableFilter(fromTable.getName())) { // 过滤退出执行 return; } join.setOnExpression(builderExpression(join.getOnExpression(), fromTable)); } } /** * 处理条件 */ protected Expression builderExpression(Expression expression, Table table) { //生成字段名 EqualsTo equalsTo = new EqualsTo(); equalsTo.setLeftExpression(this.getAliasColumn(table)); equalsTo.setRightExpression(tenantHandler.getTenantId()); //加入判断防止条件为空时生成 "and null" 导致查询结果为空 if (expression == null) { return equalsTo; } else { if (expression instanceof BinaryExpression) { BinaryExpression binaryExpression = (BinaryExpression) expression; if (binaryExpression.getLeftExpression() instanceof FromItem) { processFromItem((FromItem) binaryExpression.getLeftExpression()); } if (binaryExpression.getRightExpression() instanceof FromItem) { processFromItem((FromItem) binaryExpression.getRightExpression()); } } return new AndExpression(equalsTo, expression); } } /** *

* 租户字段别名设置
* tableName.tenantId 或 tableAlias.tenantId *

* * @param table 表对象 * @return 字段 */ protected Column getAliasColumn(Table table) { StringBuilder column = new StringBuilder(); if (null == table.getAlias()) { column.append(table.getName()); } else { column.append(table.getAlias().getName()); } column.append("."); column.append(this.tenantHandler.getTenantIdColumn()); return new Column(column.toString()); } public TenantHandler getTenantHandler() { return tenantHandler; } public void setTenantHandler(TenantHandler tenantHandler) { this.tenantHandler = tenantHandler; } }