ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

mybatis 拦截器 给所有表的sql增删改查操作加上某个字段,配合springboot

2021-01-07 15:01:15  阅读:173  来源: 互联网

标签:拦截器 return springboot 改查 private statement new public String


mybatis 拦截器
有个需求需要对所有表新增一个字段resource_mark,来区分环境,但代码已经开发好,一个个添加麻烦,并且每个表都会有这个字段。
解决方法:mybatis拦截器

@Configuration
public class MyBatisConfig {
    private final static Logger logger = LoggerFactory.getLogger(MyBatisConfig.class);
 
//设计到的表,在配置文件配置,为空则代表全部
    @Value("${mybatis.rewrite.tables:''}")
    private String rewriteTables;

    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    @PostConstruct
    public void addMySqlInterceptor() {

        logger.info("=======================MyBatis Plugin=======================");
        logger.info("=======================RewriteTables[{}]=======================",
                rewriteTables.replace("|", ";"));

        ResourceMarkInterceptor interceptor = new ResourceMarkInterceptor();
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {

            // 添加自定义属性
            interceptor.setProperties(new Properties() {{

                setProperty("resourceMarkTables", rewriteTables.replace("|", ";"));
                setProperty("enableSaaS", "true");
                setProperty("resourceMarkColumnName", "resource_mark");
                setProperty("enableJoinSelect", "true");
                setProperty("enableResourceMarkIsNull", "false");
            }});

            sqlSessionFactory.getConfiguration().addInterceptor(interceptor);

        }
    }

}


//mybatis拦截器拦截所有sql,修改我的的sql增加公用字段
@Intercepts({@Signature(
        type = StatementHandler.class,
        method = "prepare",
        args = {Connection.class, Integer.class}
)})
public class ResourceMarkInterceptor implements Interceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(ResourceMarkInterceptor.class);
    private RewriteSqlService rewriteSqlService = new RewriteSqlService();
    private static final String PAGE_OFFSET = "OFFSET";
    private static final String ENABLE_SAAS_PROPERTY = "enableSaaS";
    private static final String ENABLE_RESOURCE_MARK_ISNULL = "enableResourceMarkNull";
    private static final String ENABLE_JOIN_SELECT_PROPERTY = "enableJoinSelect";
    private static final String RESOURCE_MARK_TABLES_PROPERTY = "resourceMarkTables";
    private static final String RESOURCE_MARK_COLUMN_NAME = "resourceMarkColumnName";
    private boolean enableSaaS = true;
    private boolean enableResourceMarkNull = false;

    public ResourceMarkInterceptor() {

    }

    private void process(StatementHandler handler) {
        if (!this.isEnableSaaS()) {
            LOGGER.debug("ResourceMarkInterceptor Interceptor skip ");
        } else if (this.isEnableResourceMarkNull() && ResourceMarkInquirer.resourceMark == null) {
            LOGGER.debug("ResourceMarkInterceptor Interceptor skip ");
        } else {
            MetaObject mo;
            if (handler instanceof RoutingStatementHandler) {
                mo = SystemMetaObject.forObject(handler);
                this.process((StatementHandler) mo.getValue("delegate"));
            } else {
                mo = SystemMetaObject.forObject(handler);
                BoundSql boundSql = (BoundSql) mo.getValue("boundSql");
                String originalSql = boundSql.getSql();
                String modifiedSql = this.rewriteSqlService.dispatch(originalSql);
                modifiedSql = this.doPage(modifiedSql);
                MetaObject boundSqlMo = SystemMetaObject.forObject(boundSql);
                boundSqlMo.setValue("sql", modifiedSql);
            }
        }
    }

    private String doPage(String modifiedSql) {
        return modifiedSql.contains(PAGE_OFFSET) ? modifiedSql.replace(PAGE_OFFSET, ",") : modifiedSql;
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler handler = (StatementHandler) invocation.getTarget();
        this.process(handler);
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return target instanceof StatementHandler ? Plugin.wrap(target, this) : target;
    }

    @Override
    public void setProperties(Properties properties) {
        String enableSaaS = properties.getProperty(ENABLE_SAAS_PROPERTY, "true");
        String enableResourceMarkIsNull = properties.getProperty(ENABLE_RESOURCE_MARK_ISNULL, "false");
        String enableJoinSelect = properties.getProperty(ENABLE_JOIN_SELECT_PROPERTY, "false");
        String tenantIdTables = properties.getProperty(RESOURCE_MARK_TABLES_PROPERTY);
        String tenantIdColumnName = properties.getProperty(RESOURCE_MARK_COLUMN_NAME);
        this.setEnableSaaS(Boolean.parseBoolean(enableSaaS));
        this.setResourceMarkTables(tenantIdTables);
        this.setEnableResourceMarkNull(Boolean.parseBoolean(enableResourceMarkIsNull));
        this.rewriteSqlService.setTargetColumn(new ResourceMarkColumn(tenantIdColumnName));
        this.rewriteSqlService.setEnableJoinSelect(Boolean.valueOf(enableJoinSelect));
        this.rewriteSqlService.setEnableResourceMarkIsNull(Boolean.valueOf(enableResourceMarkIsNull));
    }

    public void setEnableSaaS(boolean enableSaaS) {
        this.enableSaaS = enableSaaS;
    }

    public void setEnableResourceMarkNull(boolean enableResourceMarkNull) {
        this.enableResourceMarkNull = enableResourceMarkNull;
    }

    public void setResourceMarkTables(String tenantIdTables) {
        if (Strings.isNullOrEmpty(tenantIdTables) && this.isEnableSaaS()) {
            this.rewriteSqlService.setRewriteAllTables(true);
        } else {
            String[] tables = tenantIdTables.split(";");
            this.rewriteSqlService.setNeedRewriteTables(Sets.newHashSet(tables));
        }
    }

    public boolean isEnableSaaS() {
        return this.enableSaaS;
    }

    public boolean isEnableResourceMarkNull() {
        return this.enableResourceMarkNull;
    }
}

@Component
public class ResourceMarkInquirer {
    public static Integer resourceMark;
    //配置字段的值
    @Value("${resource.mark:0}")
    public void setResourceMark(Integer resourceMark) {
        ResourceMarkInquirer.resourceMark = resourceMark;
    }
}
public class ResourceMarkColumn implements TargetColumn {
    private String columnName = "resource_mark";

    @Override
    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }

    @Override
    public String getColumnName() {
        return this.columnName;
    }

  //拿到字段的值,配置文件的配置
    @Override
    public Number getColumnValue() {
        return ResourceMarkInquirer.resourceMark;
    }

    public ResourceMarkColumn(String columnName) {
        this.columnName = columnName;
    }
}

//对sql的修改
public class RewriteSqlService {
    private static final Logger LOGGER = LoggerFactory.getLogger(RewriteSqlService.class);
    private TargetColumn targetColumn;
    private Set<String> needRewriteTables = new HashSet();
    private Boolean rewriteAllTables;
    private Boolean enableJoinSelect;
    private Boolean enableResourceMarkIsNull;
    private final CCJSqlParserManager parserManager;

    public RewriteSqlService() {
        this.rewriteAllTables = Boolean.FALSE;
        this.enableJoinSelect = Boolean.FALSE;
        this.enableResourceMarkIsNull = Boolean.FALSE;
        this.parserManager = new CCJSqlParserManager();
    }

    public String dispatch(String original) {
        try {
            Statement statement = this.parserManager.parse(new StringReader(original));
            if (this.isNeedRewrite(statement)) {
                if (!this.enableResourceMarkIsNull && ResourceMarkInquirer.resourceMark == null) {
                    LOGGER.error("Sql 需要rewrite. sql={}", original);
                    throw new RuntimeException(String.format("Sql 需要rewrite. sql=%s", new Object[]{original}));
                } else if (statement instanceof Select) {
                    return this.rewriteSelect((Select) statement);
                } else if (statement instanceof Delete) {
                    return this.rewriteDelete((Delete) statement);
                } else if (statement instanceof Insert) {
                    return this.rewriteInsert((Insert) statement);
                } else if (statement instanceof Update) {
                    return this.rewriteUpdate((Update) statement);
                } else {
                    LOGGER.error("unsupported sql! original sql={}", original);
                    throw new IllegalArgumentException("unsupported sql");
                }
            } else {
                return original;
            }
        } catch (TokenMgrError | JSQLParserException var3) {
            LOGGER.error("Sql 解析出错! sql={}, exception={}", original, var3);
            throw new RuntimeException(String.format("Sql 解析出错. sql=%s", new Object[]{original}), var3);
        }
    }


    private boolean isNeedRewrite(Statement statement) {
        if (statement instanceof Select) {
            Select select = (Select) statement;
            SelectBody selectBody = select.getSelectBody();
            if (selectBody instanceof PlainSelect) {
                PlainSelect ps = (PlainSelect) select.getSelectBody();
                FromItem fromItem = ps.getFromItem();
                if (fromItem instanceof Table) {
                    if (ps.getWhere() != null && ps.getWhere().toString().contains(this.getTenantColumnName())) {
                        return false;
                    }

                    List<Join> joins = ps.getJoins();
                    if (joins != null && !joins.isEmpty() && this.isEnableJoinSelect()) {
                        List<Table> tables = Lists.newArrayList(new Table[]{(Table) fromItem});
                        Iterator var8 = joins.iterator();

                        while (var8.hasNext()) {
                            Join join = (Join) var8.next();
                            if (join.getRightItem() instanceof Table) {
                                tables.add((Table) join.getRightItem());
                            }
                        }

                        var8 = tables.iterator();

                        Table table;
                        do {
                            if (!var8.hasNext()) {
                                return false;
                            }

                            table = (Table) var8.next();
                        } while (!this.isNeedRewrite(table));

                        return true;
                    }

                    return this.isNeedRewrite((Table) fromItem);
                }
            }

            return false;
        } else if (statement instanceof Insert) {
            Insert insert = (Insert) statement;
            return this.isNeedRewrite(insert.getTable());
        } else if (!(statement instanceof Update)) {
            if (statement instanceof Delete) {
                Delete delete = (Delete) statement;
                return this.isNeedRewrite(delete.getTable());
            } else if (statement instanceof Replace) {
                Replace replace = (Replace) statement;
                return this.isNeedRewrite(replace.getTable());
            } else {
                LOGGER.error("unsupported sql! statement={}", statement);
                throw new IllegalArgumentException("unsupported sql");
            }
        } else {
            Update update = (Update) statement;
            List<Table> tables = update.getTables();
            boolean flag = false;

            Table table;
            for (Iterator var5 = tables.iterator(); var5.hasNext(); flag = this.isNeedRewrite(table)) {
                table = (Table) var5.next();
            }

            if (flag && tables.size() > 1) {
                LOGGER.error("不能处理多表 statement={}", statement);
                throw new RuntimeException("不能处理多表");
            } else {
                return flag;
            }
        }
    }

    public String rewriteInsert(Insert insert) throws JSQLParserException {
        List<Column> columns = insert.getColumns();
        Table t = insert.getTable();
        Column column = new Column(this.getTenantColumnName());
        columns.add(column);
        ItemsList itemsList = insert.getItemsList();
        MultiExpressionList multiExpressionList;
        if (itemsList instanceof ExpressionList) {
            multiExpressionList = new MultiExpressionList();
            multiExpressionList.addExpressionList((ExpressionList) itemsList);
        } else {
            multiExpressionList = (MultiExpressionList) itemsList;
        }

        Iterator var7 = multiExpressionList.getExprList().iterator();

        while (var7.hasNext()) {
            ExpressionList expressionList = (ExpressionList) var7.next();
            List<Expression> expressions = expressionList.getExpressions();
            Expression valueExpression = CCJSqlParserUtil.parseExpression(this.getTenantColumnValue().toString());
            expressions.add(valueExpression);
        }

        insert.setItemsList(multiExpressionList);
        return insert.toString();
    }

    public String rewriteInsertForDealerId(BoundSql boundSql, Insert insert) throws JSQLParserException {
        List<Column> columns = insert.getColumns();
        int index = this.getTenantColumnIndex(columns);
        if (index >= 0) {
            LOGGER.warn("insert domain contains tenant column, columns={}, tenantColumn={}", columns, this.getTenantColumnName());
            columns.remove(index);
        }

        Table t = insert.getTable();
        Column column = new Column(t, this.getTenantColumnName());
        columns.add(column);
        ItemsList itemsList = insert.getItemsList();
        MultiExpressionList multiExpressionList;
        if (itemsList instanceof ExpressionList) {
            multiExpressionList = new MultiExpressionList();
            multiExpressionList.addExpressionList((ExpressionList) itemsList);
        } else {
            multiExpressionList = (MultiExpressionList) itemsList;
        }

        Iterator var9 = multiExpressionList.getExprList().iterator();

        while (var9.hasNext()) {
            ExpressionList expressionList = (ExpressionList) var9.next();
            List<Expression> expressions = expressionList.getExpressions();
            if (index >= 0) {
                expressions.remove(index);
            }

            Expression valueExpression = CCJSqlParserUtil.parseExpression(this.getTenantColumnValue().toString());
            expressions.add(valueExpression);
        }

        insert.setItemsList(multiExpressionList);
        if (index >= 0) {
            this.removeParameter(boundSql.getParameterMappings());
        }

        return insert.toString();
    }

    private String getTenantColumnName() {
        return this.targetColumn.getColumnName();
    }

    private Number getTenantColumnValue() {
        return this.targetColumn.getColumnValue();
    }

    public String rewriteUpdate(Update update) throws JSQLParserException {
        List<Table> tables = update.getTables();
        Expression where;
        if (CollectionUtils.isEmpty(tables) || tables.size() > 1) {
            // 目前只处理单表的SQL
            LOGGER.info("目前只处理单表的SQL");
            where = this.modifyWhere(update.getWhere());
            update.setWhere(where);
            return update.toString();
        }
        Table table = tables.get(0);
        Map<String, String> needRewriteTables = new HashMap<>();
        needRewriteTables.put(table.getName(), null);
        where = this.modifyWhere(update.getWhere(), needRewriteTables);
        update.setWhere(where);
        return update.toString();
    }

    public String rewriteDelete(Delete delete) throws JSQLParserException {
        Table table = delete.getTable();
        Map<String, String> needRewriteTables = new HashMap<>();
        needRewriteTables.put(table.getName(), null);
        Expression where = this.modifyWhere(delete.getWhere(), needRewriteTables);
        delete.setWhere(where);
        return delete.toString();
    }

    public String rewriteSelect(Select select) throws JSQLParserException {
        PlainSelect ps = (PlainSelect) select.getSelectBody();
        Map<String, String> needRewriteTables = this.getNeedRewriteTables(ps);
        if (!needRewriteTables.isEmpty()) {
            Expression where = this.modifyWhere(ps.getWhere(), needRewriteTables);
            ps.setWhere(where);
        }

        return ps.toString();
    }

    private Map<String, String> getNeedRewriteTables(PlainSelect ps) {
        Map<String, String> tableNameToAliasMap = Maps.newHashMap();
        List<Table> tables = Lists.newArrayList();
        FromItem fromItem = ps.getFromItem();
        if (fromItem instanceof Table) {
            Table table = (Table) fromItem;
            if (this.isNeedRewrite(table.getName())) {
                tables.add(table);
            }
        }

        List<Join> joins = ps.getJoins();
        Iterator var6;
        if (!CollectionUtils.isEmpty(joins) && this.isEnableJoinSelect().booleanValue()) {
            var6 = joins.iterator();

            while (var6.hasNext()) {
                Join join = (Join) var6.next();
                if (join.getRightItem() instanceof Table) {
                    Table table = (Table) join.getRightItem();
                    if (this.isNeedRewrite(table.getName())) {
                        tables.add((Table) join.getRightItem());
                    }
                }
            }
        }

        var6 = tables.iterator();

        while (var6.hasNext()) {
            Table table = (Table) var6.next();
            if (table.getAlias() == null) {
                tableNameToAliasMap.put(table.getName(), (String) null);
            } else {
                tableNameToAliasMap.put(table.getName(), table.getAlias().getName());
            }
        }

        return tableNameToAliasMap;
    }

    private Expression modifyWhere(Expression where) throws JSQLParserException {
        if (where == null) {
            Statement statement = this.parserManager.parse(new StringReader("select * from a where 1 = 1"));
            Select select = (Select) statement;
            PlainSelect ps = (PlainSelect) select.getSelectBody();
            where = ps.getWhere();
        }

        Expression leftExpression = this.addParenthesis(where);
        return leftExpression;
    }

    private Expression modifyWhere(Expression where, Map<String, String> tableNameToAliasMap) throws JSQLParserException {
        Select select;
        if (where == null) {
            Statement statement = this.parserManager.parse(new StringReader("select * from a where 1 = 1"));
            select = (Select) statement;
            PlainSelect ps = (PlainSelect) select.getSelectBody();
            where = ps.getWhere();
        }

        Expression leftExpression = where;

        Expression rightExpression;
        for (Iterator var10 = tableNameToAliasMap.entrySet().iterator(); var10.hasNext(); leftExpression = new AndExpression(leftExpression, rightExpression)) {
            Map.Entry<String, String> entry = (Map.Entry) var10.next();
            StringBuilder tenantColumnName = new StringBuilder();
            if (entry.getValue() != null) {
                tenantColumnName.append(entry.getValue()).append(".").append(this.getTenantColumnName());
                rightExpression = this.addParenthesis(this.getEqualsTo(tenantColumnName.toString(), this.getTenantColumnValue()));
            } else {
                tenantColumnName.append(entry.getKey()).append(".").append(this.getTenantColumnName());
                rightExpression = this.addParenthesis(this.getEqualsTo(tenantColumnName.toString(), this.getTenantColumnValue()));
            }
        }

        return leftExpression;
    }

    private boolean isNeedRewrite(Table table) {
        return this.isNeedRewrite(table.getName());
    }

    private boolean isNeedRewrite(String tableName) {
        return this.rewriteAllTables ? true : this.needRewriteTables.contains(tableName.toLowerCase());
    }

    private Expression getInExpression(String name, String value) {
        InExpression inExpression = new InExpression();
        inExpression.setLeftExpression(new Column(name));
        List<Expression> expressionList = new ArrayList();
        String[] values = value.split(",");
        String[] var6 = values;
        int var7 = values.length;

        for (int var8 = 0; var8 < var7; ++var8) {
            String s = var6[var8];
            expressionList.add(new Column(s));
        }

        ItemsList list = new ExpressionList(expressionList);
        inExpression.setRightItemsList(list);
        return inExpression;
    }

    private Expression getEqualsTo(String name, Number value) {
        EqualsTo equalsTo = new EqualsTo();
        equalsTo.setLeftExpression(new Column(name));
        equalsTo.setRightExpression(new Column(value.toString()));
        return equalsTo;
    }

    private Expression addParenthesis(Expression expression) {
        return new Parenthesis(expression);
    }

    public Set<String> getNeedRewriteTables() {
        return this.needRewriteTables;
    }

    public void setNeedRewriteTables(Set<String> needRewriteTables) {
        LOGGER.info(" MyBatis Interceptor for has tables to set  tenantId tables={}", needRewriteTables);
        this.needRewriteTables = needRewriteTables;
    }

    public Boolean isEnableJoinSelect() {
        return this.enableJoinSelect;
    }

    public void setEnableJoinSelect(Boolean enableJoinSelect) {
        this.enableJoinSelect = enableJoinSelect;
    }

    public Boolean isRewriteAllTables() {
        return this.rewriteAllTables;
    }

    public void setRewriteAllTables(Boolean rewriteAllTables) {
        this.rewriteAllTables = rewriteAllTables;
    }

    public void setEnableResourceMarkIsNull(Boolean enableResourceMarkIsNull) {
        this.enableResourceMarkIsNull = enableResourceMarkIsNull;
    }

    private int getTenantColumnIndex(List<Column> columns) {
        if (CollectionUtils.isEmpty(columns)) {
            return -1;
        } else {
            for (int i = 0; i < columns.size(); ++i) {
                Column column = (Column) columns.get(i);
                if (Objects.equals(column.getColumnName(), this.getTenantColumnName())) {
                    return i;
                }
            }

            return -1;
        }
    }

    public void setTargetColumn(TargetColumn targetColumn) {
        this.targetColumn = targetColumn;
    }

    private void removeParameter(List<ParameterMapping> parameterMappingList) {
        Iterator iterator = parameterMappingList.iterator();

        while (true) {
            ParameterMapping mapping;
            do {
                if (!iterator.hasNext()) {
                    return;
                }

                mapping = (ParameterMapping) iterator.next();
            }
            while (!Objects.equals(mapping.getProperty(), HumpLineUtils.lineToHump(this.getTenantColumnName())) && !mapping.getProperty().contains(HumpLineUtils.lineToHump(this.getTenantColumnName())));

            LOGGER.debug("remove tenant column parameter, mapping={}, tenantColumn={}", mapping.getProperty(), this.getTenantColumnName());
            iterator.remove();
        }
    }
}

标签:拦截器,return,springboot,改查,private,statement,new,public,String
来源: https://blog.csdn.net/weixin_38729746/article/details/112309411

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有