DelFlagHandler
代码、一模一样、压根没改
public interface DelFlagHandler {
Expression getTenantId();
String getTenantIdColumn();
boolean doTableFilter(String tableName);
}
DelFlagSqlParser
删除标识Sql解析器、做了一点小改动、移除了 delete
和 insert
相关功能
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<Table> 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<Join> 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);
}
}
}
/**
* 删除标识字段别名设置
* <p>tableName.tenantId 或 tableAlias.tenantId</p>
*
* @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<Join> 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<Join> 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
这个时候因为 主表为B
而 B
不满足this.tenantHandler.doTableFilter(fromTable.getName())
这句话、所以 SQL 解析退出了 、表A的多租户字段并没有被追加、这个也是主要根据多租户场景设计的、因为多租户场景有需要这种业务的情况基本为零、不需要进行租户解析
的表不多、也就几个全局表
、而且基本不会存在根据全局表
去关联查询需要解析的表
的
而以上我的改动后、就算主表不是解析表
SQL解析也会执行下去、主要我的业务逻辑是这样、只有一部分表需要 删除标识
而有一部分是不需要的、恰恰我那些不需要的表 和 删除标识
表有关联、这个时候我业务上又要求删除标识
为删除的情况下、其外键表都查不到相关的数据、所以我改成了这个处理方式、然后sql
里面用 inner join
去关联、那些外键表的数据就逻辑不存在了、也可以用 left join
去查询,这样外键表数据就存在了、只不过外键
对应的那个属性名称不存在罢了
processPlainSelect
方法中的这一部分代码还是要根据实际业务情况来的、有的系统外键走缓存、不做关联查询、这个时候需要怎么处理、具体要看业务、我这里提供的代码仅供参考、也是方便我自己以后copy的
使用方法的话、就是参考多租户
的使用方法、MyBatis-Plus
的版本为 3.1.1