原创

Mybatis-mybatis-plus-tkmabatis-表前缀设置-全局Interceptor拦截替换sql表前缀

mybatis-plus相关配置,按需使用

mybatis-plus:
  global-config:
    db-config:
      #tk方法的表前缀
      table-prefix: ${spring.application.name}_
  configuration-properties:
    # 自定义sql中表名带前缀 https://www.cnblogs.com/javalinux/p/14338780.html
    # prefix 是内置参数
    prefix: ${spring.application.name}_
    # key1等是自定义的,使用时直接${key1} ,但是不要使用#
    # key1: 2222
    configuration:
   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:mapper/*.xml

全局替换sql表前缀

package cn.jiangjiesheng.inp.aspect;


import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.sql.Connection;

/**
 * 自定义 MyBatis 拦截器
 */
// https://blog.csdn.net/weixin_34082854/article/details/86452841

/**
 * method:表示拦截的方法,mybatis支持的方法有 update, query, flushStatements, commit, rollback, getTransaction, close, isClosed
 * 方法,其中,update包括新增、修改、删除等方法,query用于查询,其它的基本用不到。
 * args:表示拦截的参数类型,有MappedStatement、Object、RowBounds和ResultHandler等等.
 * type:表示拦截的类,有Executor、StatementHandler、ParameterHandler和ResultSetHandler。
 *
 *
 * 实际使用时要测试 tkmybatis代码直接使用、mapper xml、@Insert注解类的sql的增删改查
 *
 */
@Component
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
@Slf4j
public class MySqlInterceptor implements Interceptor {

    private static final Logger logger= LoggerFactory.getLogger(MySqlInterceptor.class);

    @Value("${spring.application.name}")
    private String springApplicationName;

    /**
     * intercept 方法用来对拦截的sql进行具体的操作
     * @param invocation
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //logger.info("执行intercept方法:{}", invocation.toString());

        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        BoundSql boundSql = statementHandler.getBoundSql();
        String origSql = boundSql.getSql();
        //logger.info("原始SQL: {}", origSql);

        // 组装新的 sql
        //这种需要代码中的默认都是应inp来
        if(!origSql.contains("newinp_") && "newinp".equals(springApplicationName)){
            String newSql = origSql.replaceAll("inp_",springApplicationName+"_");
            //logger.info("改写的SQL: {}", newSql);
            Field field = boundSql.getClass().getDeclaredField("sql");
            field.setAccessible(true);
            field.set(boundSql, newSql);
        }

        return invocation.proceed();
    }


    @Override
    public Object plugin(Object target) {
       // 这里的实现非常关键,是保证@Intercepts注解、intercept方法能不能进来的判断开关
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

}

如果sql拦截不生效【重要】

package spcommon.config;

import com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Properties;

@Configuration
@AutoConfigureAfter(PageHelperAutoConfiguration.class)
public class MyBatisConfig {

    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    @PostConstruct
    public void addMySqlInterceptor() {
        MySqlInterceptor interceptor = new MySqlInterceptor(); //上述示例

        MySqlInsertValueInterceptor handleInsertValueInterceptor = new MySqlInsertValueInterceptor(); //实际应用
        MySqlSelectResultInterceptor handleSelectResultIInterceptor = new MySqlSelectResultInterceptor();//实际应用


        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {

            // 添加自定义属性
//            Properties properties = new Properties();
//            properties.setProperty("prop1", "value1");
//            interceptor.setProperties(properties);
            sqlSessionFactory.getConfiguration().addInterceptor(interceptor);

            sqlSessionFactory.getConfiguration().addInterceptor(handleInsertValueInterceptor);
            sqlSessionFactory.getConfiguration().addInterceptor(handleSelectResultIInterceptor);


        }
    }

}

在 resources 目录下创建META-INF目录下,在 META-INF 目录下创建 spring.factories 文件,文件内容如下:


xxx.xxx.MyBatisConfig

实际使用1 去掉mybatis insert sql 中的 空值字段**

package cn.jiangjiesheng.edu.config.datasource;


import com.google.common.collect.Lists;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import org.apache.logging.log4j.util.Strings;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.persistence.Column;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 自定义 MyBatis 拦截器
 */
// https://blog.csdn.net/weixin_34082854/article/details/86452841

/**
 * method:表示拦截的方法,mybatis支持的方法有 update, query, flushStatements, commit, rollback, getTransaction, close, isClosed
 * 方法,其中,update包括新增、修改、删除等方法,query用于查询,其它的基本用不到。
 * args:表示拦截的参数类型,有MappedStatement、Object、RowBounds和ResultHandler等等.
 * type:表示拦截的类,有Executor、StatementHandler、ParameterHandler和ResultSetHandler。
 * <p>
 * <p>
 * 实际使用时要测试 tkmybatis代码直接使用、mapper xml、@Insert注解类的sql的增删改查
 */
@Component
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
@Slf4j
public class MySqlInsertValueInterceptor implements Interceptor {

    @Value("${spring.application.name}")
    private String springApplicationName;

    private static String INVALID_SYMBOL = "[\r\n\t]";
    public static String BLANK = " ";
    public static String MORE_BLANK = BLANK + BLANK;
    private final static String INSERT_INFO_KEY = "INSERT ";//INTO
    private final static String INSERT_INFO_PK_ID = "id";

    /**
     * intercept 方法用来对拦截的sql进行具体的操作
     *
     * @param invocation
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //logger.info("执行intercept方法:{}", invocation.toString());

        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        BoundSql boundSql = statementHandler.getBoundSql();
        String origSql = boundSql.getSql().replaceAll(INVALID_SYMBOL, "");

        origSql = replaceMoreBlank(origSql);

        //logger.info("原始SQL: {}", origSql);

        if (origSql.contains(INSERT_INFO_KEY)) {

            //为空的字段
            Object parameterObject = boundSql.getParameterObject();
            if (parameterObject != null) {

                //获取到所有的字段
                List<String> filedList = Arrays.asList(origSql.substring(origSql.indexOf("(") + 1, origSql.indexOf("VALUES") - 2).replaceAll(" ", "").split(","));

                boolean isMap = parameterObject instanceof Map;
                if (isMap) {
                    //批量插入的,就把空字符串的改成两个空格
                    setEmptyStringToBlankForBatchInsert(parameterObject, filedList);
                } else {
                    //单条插入插入的,就把空字符串的字段都去掉(不适合批量插入的场景)
                    //TODO 1 关注
                    //  @Column(name = "enterprise_id")
                    //  private String containerId;  对于这种无法判断,所以由于所有的字段都把not null 去掉了 ,但是现有表还有 not null的id,所以值处理id吧。如果不是有id,可能本class类都可以不用了
                    //要映射成和 @Column(name = "enterprise_id") 字段相同的

//
//                @Column(name = "enterprise_id")
//                @ApiModelProperty(value = "容器(企业)ID")
//                private String containerId;
                    //需要重写setContainerId,给数据库的实际字段增加一个赋值
//                private String enterpriseId;
//
//                public void setContainerId(String containerId) {
//                    this.containerId = containerId;
//                    this.enterpriseId = containerId;
//                }
                    NotNullFieldListVo notNullFieldListVo = getNotNullFieldList(parameterObject, filedList);

                    List<String> notNullDatabaseFieldList = notNullFieldListVo.getNotNullDatabaseFiledList();
                    List<String> notNullEntityField = notNullFieldListVo.getNotNullEntityField();
//                List<String> notNullDatabaseFieldList  = Lists.newArrayList(filedList);
//                notNullDatabaseFieldList.remove(INSERT_INFO_PK_ID);

                    String newSql = getNoNullInsertSql(origSql, notNullDatabaseFieldList);

                    Field field = boundSql.getClass().getDeclaredField("sql");
                    //重要
                    field.setAccessible(true);
                    field.set(boundSql, newSql);

                    int batchCount = newSql.split("\\),\\(").length;
                    if (batchCount == 1) {
                        //TODO 1 关注
                        //  @Column(name = "enterprise_id") itemAnalysisPic
                        //  private String containerId;  对于这种无法判断,所以由于所有的字段都把not null 去掉了 ,但是现有表还有 not null的id,所以值处理id吧。如果不是有id,可能本class类都可以不用了

                        List<String> notNullTufenFieldList = covert2TuofengField4check(notNullDatabaseFieldList);
                        List<ParameterMapping> getParameterMappings = boundSql.getParameterMappings().stream().
                                filter(parameterMapping -> {
                                    String property = getProperty(parameterMapping);
                                    return notNullTufenFieldList.contains(property) || notNullEntityField.contains(property);
                                })
                                .distinct().collect(Collectors.toList());
                        Field fieldParameterMappings = boundSql.getClass().getDeclaredField("parameterMappings");
                        //重要
                        fieldParameterMappings.setAccessible(true);
                        fieldParameterMappings.set(boundSql, getParameterMappings);

//                    List<ParameterMapping> getParameterMappings = boundSql.getParameterMappings().stream().
//                            filter(y -> !INSERT_INFO_PK_ID.equals(getProperty(y)))
//                            .distinct().collect(Collectors.toList());
//                    Field fieldParameterMappings = boundSql.getClass().getDeclaredField("parameterMappings");
//                    fieldParameterMappings.setAccessible(true);
//                    fieldParameterMappings.set(boundSql, getParameterMappings);
                    }
                }
            }

        }

        return invocation.proceed();
    }

    @NotNull
    private String getProperty(ParameterMapping y) {
        String property = y.getProperty().replaceAll("`", "");
        if (property.contains(".")) {
            property = property.substring(property.lastIndexOf(".") + 1);
        }
        return property;
    }

    @Override
    public Object plugin(Object target) {
        // 这里的实现非常关键,是保证@Intercepts注解、intercept方法能不能进来的判断开关
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }


    private NotNullValueFieldVo isNotNullValueField(Object parameterObject, String databaseFiled) {
        Field field = null;
        NotNullValueFieldVo vo = new NotNullValueFieldVo();
        try {
            //带` 这种关键字的不知道怎么办
            //

            String filed = covert2TuofengField(databaseFiled);

            //field = parameterObject.getClass().getDeclaredField(filed.replaceAll("`", ""));

            Class cls = null;
            boolean isMap = parameterObject instanceof Map;
            if (isMap) {
                //这里实际不走了 【批量场景】


                //这种一般是mapper中自定义sql做的批量插入 所以这种 字段,除了id,其他都认为非空吧,满意真的要空,那在代码中设置值,或者在表结构设上把not null 去掉
                if (INSERT_INFO_PK_ID.toLowerCase().equals(filed.toLowerCase())) {
                    List list = (List) ((MapperMethod.ParamMap) parameterObject).entrySet().toArray()[0];
                    cls = list.get(0).getClass();
                } else {
                    vo.setIsNotNullValue(true);
                    vo.setEntityField(filed);
//                    return true;
                    return vo;
                }

//                Object[] objects = ((MapperMethod.ParamMap) parameterObject).entrySet().toArray();
//                for (int i = 0; i < objects.length; i++) {
//                    List ListValue = (List) ((Map.Entry) objects[i]).getValue();
//                    for (Object o : ListValue) {
//                        cls = o.getClass();
//                        field = getFieldIncludeSuper(cls, filed.replaceAll("`", ""), databaseFiled.replaceAll("`", ""));
//                        field.setAccessible(true);
//                        Object value = field.get(o);
//
//                        if (Strings.EMPTY.equals(value)) {
//                            //TODO oracle,空字符串会认为是null
//                            field.set(o, BLANK);
//                        }
//                    }
//
//                }

//                List value = (List) ((Map.Entry) objects[0]).getValue();
//                List value2 = (List) ((Map.Entry) ((MapperMethod.ParamMap) parameterObject).entrySet().toArray()[1]).getValue();

                cls = ((List) ((Map.Entry) ((MapperMethod.ParamMap) parameterObject).entrySet().toArray()[0]).getValue()).get(0).getClass();

            } else {
                cls = parameterObject.getClass();
            }

            field = getFieldIncludeSuper(cls, filed.replaceAll("`", ""), databaseFiled.replaceAll("`", ""));
            //重要
            field.setAccessible(true);
            Object value = field.get(parameterObject);

            if (Strings.EMPTY.equals(value)) {
                //TODO oracle,空字符串会认为是null
                field.set(parameterObject, BLANK); //还是也认为是空?
                value = BLANK;
            }
//            return value != null;
            vo.setIsNotNullValue(value != null);
            vo.setEntityField(field.getName());
            return vo;

        } catch (Exception e) {
//            e.printStackTrace();
        }
        vo.setIsNotNullValue(false);
        vo.setEntityField(null);
        return vo;
    }

    private void setEmptyStringToBlankForBatchInsert(Object parameterObject,  List<String> databaseFiledList){
        Class cls = null;
        Object[] objects = ((MapperMethod.ParamMap) parameterObject).entrySet().toArray();
        for (String databaseFiled : databaseFiledList) {
            String filed = covert2TuofengField(databaseFiled);
            Field field = null;

            for (int i = 0; i < objects.length; i++) {
                List ListValue = (List) ((Map.Entry) objects[i]).getValue();
                for (Object o : ListValue) {
                    cls = o.getClass();
                    field = getFieldIncludeSuper(cls, filed.replaceAll("`", ""), databaseFiled.replaceAll("`", ""));
                    //重要
                    field.setAccessible(true);
                    Object value = null;
                    try {
                        value = field.get(o);
                        if (Strings.EMPTY.equals(value)) {
                            //TODO oracle,空字符串会认为是null
                            field.set(o, BLANK);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    @Data
    private class NotNullValueFieldVo {
        private Boolean IsNotNullValue;
        private String entityField;
    }


    @Data
    private class NotNullFieldListVo {
        private List<String> notNullDatabaseFiledList;
        private List<String> notNullEntityField;
    }

    //反射获取父类中的字段
    public static Field getFieldIncludeSuper(Class<?> clazz, String fieldName, String databaseFiled) {

        Class<?> clazzBak = clazz;

        Field field = null;
        while (clazz != null) {
            try {
                field = clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException ignore) {
                // log.error("获取字段失败:fieldName{},异常:{}", fieldName, ignore);
            }
            if (field == null) {
                clazz = clazz.getSuperclass();
            } else {
                break;
            }
        }

        if (field == null) {
            //还有实体字段和数据库字段不同的
            return getFieldIncludeSuperByAnnotation(clazzBak, databaseFiled);
        }
        return field;
    }

    /**
     * 根据 @Column注解获取到Field字段
     *
     * @description:
     * @author: 江节胜
     * @email: dev@jiangjiesheng.cn
     */
    public static Field getFieldIncludeSuperByAnnotation(Class<?> clazz, String databaseFiled) {
        //https://blog.csdn.net/weixin_30505485/article/details/94817025
        Field field = null;

        while (clazz != null) {
            Field[] fields = clazz.getDeclaredFields();
            for (Field field1 : fields) {
                //重要
                field1.setAccessible(true);
            }
            for (Field field1 : fields) {
                try {
                    field = clazz.getDeclaredField(field1.getName());
                    Column column = field.getAnnotation(Column.class);
                    if (column != null) {
                        //System.out.println(column.name());
                        //System.out.println(column.length());
                        String name = column.name();
                        if (StringUtils.isNotBlank(name)) {
                            if (databaseFiled.equals(column.name().replaceAll("`", ""))) {
                                return field;
                            }
                        }
                    }
                } catch (NoSuchFieldException e) {
                }
            }
            if (field == null) {
                clazz = clazz.getSuperclass();
            } else {
                break;
            }
        }
        return field;
    }

    private List<String> covert2TuofengField4check(List<String> fieldList) {
        List<String> fieldTofengList = Lists.newArrayList();
        for (String f : fieldList) {
            fieldTofengList.add(covert2TuofengField(f).replaceAll("`", ""));
        }
        return fieldTofengList;
    }

    private String covert2TuofengField(String filed) {
        if (filed.contains("_")) {
            String low = filed.substring(filed.indexOf("_"), filed.indexOf("_") + 2);
            String toUper = low.toUpperCase().replaceAll("_", "");
            filed = filed.replaceAll(low, toUper);
            return covert2TuofengField(filed);
        }
        return filed;
    }

    private NotNullFieldListVo getNotNullFieldList(Object parameterObject, List<String> filedList) {

        NotNullFieldListVo notNullFieldListVo = new NotNullFieldListVo();
        List<String> notNullDatabaseFiledList = Lists.newArrayList();
        List<String> notNullEntityFiledList = Lists.newArrayList();

        for (String f : filedList) {
            NotNullValueFieldVo notNullValueField = isNotNullValueField(parameterObject, f);
            if (notNullValueField.getIsNotNullValue()) {
                notNullDatabaseFiledList.add(f);
                notNullEntityFiledList.add(notNullValueField.getEntityField());
            }
        }
        notNullFieldListVo.setNotNullDatabaseFiledList(notNullDatabaseFiledList.stream().distinct().collect(Collectors.toList()));
        notNullFieldListVo.setNotNullEntityField(notNullEntityFiledList.stream().distinct().collect(Collectors.toList()));

        return notNullFieldListVo;
    }


    /**
     * @description: 去掉mybatis insertSelective 中的 id,避免某些嵌套的数据库环境,传入报错
     * @author: 江节胜
     * @email: dev@jiangjiesheng.cn
     * @Date 2024-01-26
     */
    private String getNoNullInsertSql(String origSql, List<String> notNullFieldList) {
        if (origSql.contains(INSERT_INFO_KEY)) {
            //INSERT INTO edu_train_category
            StringBuilder newSql = new StringBuilder(origSql.substring(0, origSql.indexOf("(") + 1));
            newSql.append(StringUtils.join(notNullFieldList, ","));
            newSql.append(") VALUES ");

            //判断一下有多少插入的条数
            String valueSql = origSql.substring(origSql.lastIndexOf("VALUES") + "VALUES".length());
            valueSql = replaceBlank(valueSql);
            int batchCount = valueSql.split("\\),\\(").length;

            for (int i = 0; i < batchCount; i++) {
                newSql.append("(");
                StringBuilder values = new StringBuilder();
                for (String f : notNullFieldList) {
                    values.append("?,");
                }
                values = new StringBuilder(values.substring(0, values.length() - 1));
                newSql.append(values);

                newSql.append(")");
                newSql.append(",");
            }
            newSql = new StringBuilder(newSql.substring(0, newSql.length() - 1));

            //去掉id字段 不能用,会把带id,的字段都改了 origSql.replace(INSERT_INFO_PK_ID, Strings.EMPTY);
            // String newSql = origSql.substring(0,origSql.indexOf(INSERT_INFO_PK_ID)) + origSql.substring(origSql.indexOf(INSERT_INFO_PK_ID)+INSERT_INFO_PK_ID.length());

            // String newSql
            //
            // 再解析一下 VALUES( ?,?,?,?,?,?,? )

            //截止到 VALUES
//            String insertSqlPrefix = newSql.substring(0, newSql.lastIndexOf("VALUES") + 6);
//            System.out.println(insertSqlPrefix);
//            // 带 ()
//            String sqlParams = newSql.substring(newSql.lastIndexOf("VALUES") + 6);
//            System.out.println(sqlParams);
//            //参数部分
//            String sqlParamsClean = sqlParams.substring(1, sqlParams.length() - 2);
//            System.out.println(sqlParamsClean);
//            //去掉第一个参数
//            sqlParamsClean = sqlParamsClean.substring(sqlParamsClean.indexOf(",") + 1);
//            System.out.println(sqlParams);
//
//            newSql = insertSqlPrefix + " (" + sqlParamsClean + ")";
//
//            System.out.println(newSql);
            return newSql.toString();

        }
        return origSql;
    }

    private String replaceMoreBlank(String value) {
        value = value.replaceAll(MORE_BLANK, BLANK);
        if (StringUtils.isBlank(value) || !value.contains(MORE_BLANK)) {
            return value;
        }
        return replaceMoreBlank(value);
    }

    private String replaceBlank(String value) {
        value = value.replaceAll(BLANK, Strings.EMPTY);
        if (StringUtils.isBlank(value) || !value.contains(BLANK)) {
            return value;
        }
        return replaceBlank(value);
    }

}

实际使用2 修改mybatis select结果值把两个空格改成空字符串

结合上述 实际使用1 “把空字符串的改成两个空格”

package cn.jiangjiesheng.edu.config.datasource;

import cn.hutool.core.util.ReflectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.List;


@Slf4j
@Intercepts({@Signature(type = Executor.class, method = "query"
        , args = {MappedStatement.class, Object.class, RowBounds.class,
        ResultHandler.class}),
        @Signature(type = Executor.class, method = "query"
                , args = {MappedStatement.class, Object.class, RowBounds.class,
                ResultHandler.class, CacheKey.class, BoundSql.class})})
@Component
public class MySqlSelectResultInterceptor implements Interceptor {


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object obj = invocation.proceed();
        try {
            if (ObjectUtils.allNull(obj)) {
                return obj;
            }
            if (!(obj instanceof List)) {
                return obj;
            }
            List<Object> objectList = (List<Object>) obj;
            for (Object object : objectList) {
                this.Handle2EmptyValue(object);
            }
            return objectList;
        } catch (Exception exception) {
            log.error("ex", exception);
            return obj;
        }
    }

    private void Handle2EmptyValue(Object object) throws IllegalAccessException {
        Class<?> aClass = object.getClass();

        Field[] fields = ReflectUtil.getFields(aClass);//包括父类
        for (Field field : fields) {
            Object o = null;
            try {
                field.setAccessible(true);
                o = field.get(object);
            } catch (Exception e) {
                continue;
            }
            if (o != null) {
                if (o instanceof String) {
                    String s = o.toString();
                    if (MySqlInsertValueInterceptor.BLANK.equals(s) || MySqlInsertValueInterceptor.MORE_BLANK.equals(s)) {
                        field.set(object, Strings.EMPTY);
                    }
                }
            }
        }
    }
}

来自anyuan刘的拦截示例


package cn.jiangjiesheng.bootstrap.qpaas.interceptor;

import com.google.common.collect.Lists;
import cn.jiangjiesheng.bootstrap.commons.context.EntContext;
import cn.jiangjiesheng.bootstrap.commons.exception.BizzException;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.List;
import java.util.Properties;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.util.validation.Validation;
import net.sf.jsqlparser.util.validation.ValidationError;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
@Intercepts({@Signature(
    type = StatementHandler.class,
    method = "prepare",
    args = {Connection.class, Integer.class}
)})
public class PaasDataPoolInterceptor implements Interceptor {
    private static final Logger log = LoggerFactory.getLogger(PaasDataPoolInterceptor.class);
    public static final CCJSqlParserManager parser = new CCJSqlParserManager();

    public PaasDataPoolInterceptor() {
    }

    private void sqlValidator(String sql) {
        Validation validation = new Validation(Lists.newArrayList(new CustomDatabaseType[]{CustomDatabaseType.SQL_92}), new String[]{sql});
        List<ValidationError> errors = validation.validate();
        if (!errors.isEmpty()) {
            log.error("PaasDataPoolInterceptor Error {}", errors);
        }

    }

    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
        BoundSql boundSql = statementHandler.getBoundSql();
        String sql = boundSql.getSql();
        SelectTableNameModifier modifier = new SelectTableNameModifier(EntContext.getEntId());
        Statement statement = parser.parse(new StringReader(sql));
        if (statement instanceof Select) {
            Select select = (Select)statement;
            select.getSelectBody().accept(modifier);
        } else if (statement instanceof Update) {
            Update select = (Update)statement;
            select.getTable().accept(modifier);
        } else {
            if (!(statement instanceof Insert)) {
                throw new BizzException("不支持的语句");
            }

            Insert select = (Insert)statement;
            select.getTable().accept(modifier);
        }

        Field declaredField = boundSql.getClass().getDeclaredField("sql");
        declaredField.setAccessible(true);
        declaredField.set(boundSql, statement.toString());
        return invocation.proceed();
    }

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

    public void setProperties(Properties properties) {
    }
}
正文到此结束
本文目录