项目需求,需要每个表添加一个机构标识, 由于来的分表合并为一个表中,通过机构标识来过滤数据。一个一个加太繁琐,所以使有了mybatis的拦截器。
先来说一下拦截器不生效的问题。开始想使用@component注解来注入拦截器,谁成想,拦截器确不生效。后来发现可能跟我的多数据源有问题。后来使用两个方法可解决,如有以下拦截器:
package com.zm.config;
import com.alibaba.nacos.common.utils.StringUtils;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.schema.Column;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.FromItem;
import net.sf.jsqlparser.statement.select.Join;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.util.deparser.ExpressionDeParser;
import net.sf.jsqlparser.statement.insert.Insert;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerMapping;
import javax.servlet.http.HttpServletRequest;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.*;
@Slf4j
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {
Connection.class, Integer.class})})
@Component
public class SqlInterceptor implements Interceptor {
private static final String COLUMN_NAME = "org_id";
// 表别名
private String tableAlias;
@Value("${his.org}")
private String orgId;
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
//通过MetaObject优雅访问对象的属性,这里是访问statementHandler的属性;:MetaObject是Mybatis提供的一个用于方便、
//优雅访问对象属性的对象,通过它可以简化代码、不需要try/catch各种reflect异常,同时它支持对JavaBean、Collection、Map三种类型对象的操作。
MetaObject metaObject = MetaObject
.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,
new DefaultReflectorFactory());
//先拦截到RoutingStatementHandler,里面有个StatementHandler类型的delegate变量,其实现类是BaseStatementHandler,然后就到BaseStatementHandler的成员变量mappedStatement
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
//id为执行的mapper方法的全路径名,如com.uv.dao.UserMapper.insertUser
String id = mappedStatement.getId();
//sql语句类型 select、delete、insert、update
String sqlCommandType = mappedStatement.getSqlCommandType().toString();
//数据库连接信息
// Configuration configuration = mappedStatement.getConfiguration();
// ComboPooledDataSource dataSource = (ComboPooledDataSource)configuration.getEnvironment().getDataSource();
// dataSource.getJdbcUrl();
String sql2Reset="";
if(SqlCommandType.SELECT.name().equals(sqlCommandType)){
Select selectStatement = (Select) CCJSqlParserUtil.parse(statementHandler.getBoundSql().getSql());
PlainSelect plain = (PlainSelect) selectStatement.getSelectBody();
FromItem fromItem = plain.getFromItem();
// 仅对枚举符合表, 并没有代理商字段的进行拼接sql
Table table = this.ifConform(plain);
if (table != null && this.doesItExist(plain.getWhere())) {
// 进行拼接, 判断是否有where
Expression where = plain.getWhere();
// 获取查询语句表别名(兼容之前做好功能一个方法表别名不一致)
String sqlTableAlias = table.getAlias() != null