MyBatis-Plus根据多租户扩展删除标识功能

DelFlagHandler 代码、一模一样、压根没改

public interface DelFlagHandler {

    Expression getTenantId();

    String getTenantIdColumn();

    boolean doTableFilter(String tableName);
}

DelFlagSqlParser 删除标识Sql解析器、做了一点小改动、移除了 deleteinsert 相关功能

public class DelFlagSqlParser extends AbstractJsqlParser {

    private DelFlagHandler delFlagHandler;

    @Override
    public void processInsert(Insert insert) {

    }

    @Override
    public void processDelete(Delete delete) {

    }

    @Override
    public void processUpdate(Update update) {
        List tableList = update.getTables();
        Assert.isTrue(null != tableList && tableList.size() < 2,
                "Failed to process multiple-table update, please exclude the statementId");
        Table table = tableList.get(0);
        if (delFlagHandler.doTableFilter(table.getName())) {
            // 过滤退出执行
            return;
        }
        update.setWhere(this.andExpression(table, update.getWhere()));

    }

    /**
     * delete update 语句 where 处理
     */
    protected BinaryExpression andExpression(Table table, Expression where) {
        //获得where条件表达式
        EqualsTo equalsTo = new EqualsTo();
        equalsTo.setLeftExpression(this.getAliasColumn(table));
        equalsTo.setRightExpression(delFlagHandler.getTenantId());
        if (null != where) {
            if (where instanceof OrExpression) {
                return new AndExpression(equalsTo, new Parenthesis(where));
            } else {
                return new AndExpression(equalsTo, where);
            }
        }
        return equalsTo;
    }

    @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);
            }
        }
    }

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

    /**
     * 处理 PlainSelect
     *
     * @param plainSelect ignore
     * @param addColumn   是否添加删除标识列,select语句中需要
     */
    protected void processPlainSelect(PlainSelect plainSelect, boolean addColumn) {
        FromItem fromItem = plainSelect.getFromItem();
        if (fromItem instanceof Table) {
            Table fromTable = (Table) fromItem;
            if (!delFlagHandler.doTableFilter(fromTable.getName())) {
                plainSelect.setWhere(builderExpression(plainSelect.getWhere(), fromTable));
                if (addColumn) {
                    plainSelect.getSelectItems().add(new SelectExpressionItem(new Column(delFlagHandler.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(this::processJoin);
            }
            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.delFlagHandler.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(delFlagHandler.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());
                }
            }
            if (expression instanceof OrExpression) {
                return new AndExpression(equalsTo, new Parenthesis(expression));
            } else {
                // fix github 1201
                if (expression instanceof InExpression) {
                    InExpression inExp = (InExpression) expression;
                    ItemsList rightItems = inExp.getRightItemsList();
                    if (rightItems instanceof SubSelect) {
                        processSelectBody(((SubSelect) rightItems).getSelectBody());
                    }
                }
                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(StringPool.DOT); column.append(delFlagHandler.getTenantIdColumn()); return new Column(column.toString()); } }

改动点位于 processPlainSelect 方法中

        FromItem fromItem = plainSelect.getFromItem();
        if (fromItem instanceof Table) {
            Table fromTable = (Table) fromItem;
            //这个位置
            if (!delFlagHandler.doTableFilter(fromTable.getName())) {
                plainSelect.setWhere(builderExpression(plainSelect.getWhere(), fromTable));
                if (addColumn) {
                    plainSelect.getSelectItems().add(new SelectExpressionItem(new Column(delFlagHandler.getTenantIdColumn())));
                }
            }
        } else {
            processFromItem(fromItem);
        }
        List joins = plainSelect.getJoins();
        if (joins != null && joins.size() > 0) {
            joins.forEach(j -> {
                processJoin(j);
                processFromItem(j.getRightItem());
            });
        }

以下是源码

        FromItem fromItem = plainSelect.getFromItem();
        if (fromItem instanceof Table) {
            Table fromTable = (Table)fromItem;
            //这里
            if (this.tenantHandler.doTableFilter(fromTable.getName())) {
                return;
            }

            plainSelect.setWhere(this.builderExpression(plainSelect.getWhere(), fromTable));
            if (addColumn) {
                plainSelect.getSelectItems().add(new SelectExpressionItem(new Column(this.tenantHandler.getTenantIdColumn())));
            }
        } else {
            this.processFromItem(fromItem);
        }

        List joins = plainSelect.getJoins();
        if (joins != null && joins.size() > 0) {
            joins.forEach((j) -> {
                this.processJoin(j);
                this.processFromItem(j.getRightItem());
            });
        }

多租户时,例如 解析表A和不解析表B、进行多表查询、from B inner join A 这个时候因为 主表为BB 不满足this.tenantHandler.doTableFilter(fromTable.getName()) 这句话、所以 SQL 解析退出了 、表A的多租户字段并没有被追加、这个也是主要根据多租户场景设计的、因为多租户场景有需要这种业务的情况基本为零、不需要进行租户解析的表不多、也就几个全局表、而且基本不会存在根据全局表去关联查询需要解析的

而以上我的改动后、就算主表不是解析表 SQL解析也会执行下去、主要我的业务逻辑是这样、只有一部分表需要 删除标识 而有一部分是不需要的、恰恰我那些不需要的表 和 删除标识 表有关联、这个时候我业务上又要求删除标识为删除的情况下、其外键表都查不到相关的数据、所以我改成了这个处理方式、然后sql里面用 inner join 去关联、那些外键表的数据就逻辑不存在了、也可以用 left join 去查询,这样外键表数据就存在了、只不过外键对应的那个属性名称不存在罢了

processPlainSelect方法中的这一部分代码还是要根据实际业务情况来的、有的系统外键走缓存、不做关联查询、这个时候需要怎么处理、具体要看业务、我这里提供的代码仅供参考、也是方便我自己以后copy的

使用方法的话、就是参考多租户的使用方法、MyBatis-Plus的版本为 3.1.1

你可能感兴趣的:(MyBatis-Plus)