Interceptor 1 :

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

    }
)
public class SelectLimitInterceptor implements Interceptor {

    public SelectLimitInterceptor() {
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        DataSourceType dataSource = DataSourceContextHolder.getDataSource();
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement)args[0];
        Object parameter = args[1];
        RowBounds rowBounds = (RowBounds) args[2];
        ResultHandler resultHandler = (ResultHandler) args[3];

        Executor executor = (Executor)invocation.getTarget();

        CacheKey cacheKey;
        BoundSql boundSql;
        if (args.length == 4) {
            boundSql = ms.getBoundSql(parameter);
            cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);

        } else {
            cacheKey = (CacheKey) args[4];
            boundSql = (BoundSql) args[5];

        }

        String sql = boundSql.getSql();
        if (DataSourceEnum.TIMESTEN.equals(dataSource)){
            sql = "Select * from (" + sql + ") t where rownum < 10000";
        } else {
            sql = "Select * from (" + sql + ") t limit 10000";
        }

        ReflectUtil.setFieldValue(boundSql, "sql", sql);
        return executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
    }

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

    @Override
    public void setProperties(Properties properties) {

    }
}

Interceptor 2 : 给默认字段赋值


@Intercepts(
    {
        @Signature(
                type = Executor.class,
                method = "update",
                args = {MappedStatement.class, Object.class}
        )
    }
)
public class FieldInterceptor implements Interceptor {

    public FieldInterceptor() {
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        try {

            Object parameter = invocation.getArgs()[1];
            MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
            SqlCommandType sqlCommandType = ms.getSqlCommandType();
            if (parameter instanceof MapperMethod.ParamMap) {
                MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap)parameter;
                final int size = paramMap.size();

                for (int i = 0; i < size/2; ++i) {
                    this.checkAndSet(paramMap.get("param"+ i), sqlCommandType);
                }

            } else if (parameter instanceof DefaultSqlSession.StrictMap) {
                List collection = (List)((DefaultSqlSession.StrictMap)parameter).get("collection");
                Iterator iterator = collection.iterator();

                while (iterator.hasNext()) {
                    Object obj = iterator.next();
                    this.checkAndSet(obj, sqlCommandType);
                }

            } else {
                this.checkAndSet(parameter, sqlCommandType);
            }

        }catch (Exception e){
            //log
        }

        return invocation.proceed();
    }

    private void checkAndSet(Object parameter, SqlCommandType sqlCommandType){
        if (parameter instanceof BaseDTO && (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType))){
            String currentName = "SYSTEM";

            BaseDTO baseDTO = (BaseDTO)parameter;
            if (StringUtils.isEmpty(baseDTO.getUpdateBy())){
                baseDTO.setUpdateBy(currentName);
            }

            if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)){
                baseDTO.setCreateBy(currentName);
            }

            if (parameter instanceof List) {
                Iterator it = ((List<?>) parameter).iterator();
                while (it.hasNext()) {
                    Object obj = it.next();
                    this.checkAndSet(obj, sqlCommandType);
                }
            }
        }
    }


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

    @Override
    public void setProperties(Properties properties) {

    }
}

将Interceptor使用Spring容器管理:


@Configuration
public class MybatisConfig {


    @Bean
    public FieldInterceptor fieldInterceptor(){
        FieldInterceptor interceptor = new FieldInterceptor();
        Properties prop = new Properties();
        prop.put("dialect", "mysql");
        interceptor.setProperties(prop);
        return interceptor;
    }

    @Bean
    public SelectLimitInterceptor selectLimitInterceptor(){
        SelectLimitInterceptor interceptor = new SelectLimitInterceptor();
        Properties prop = new Properties();
        prop.put("dialect", "mysql");
        interceptor.setProperties(prop);
        return interceptor;
    }

    @Bean(name = "dataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        List<Filter> filters = new ArrayList<>();
        filters.add(wallFilter);
        dataSource.setProxyFilters(filters);
        return dataSource;
    }

    @Bean(name = "wallFilter")
    @DependsOn("wallConfig")
    public WallFilter wallFilter(){
        WallFilter interceptor = new WallFilter();
        interceptor.setConfig(wallConfig());
        return interceptor;
    }

    @Bean(name = "wallConfig")
    public WallConfig wallConfig(){
        WallConfig wallConfig = new WallConfig();
        wallConfig.setMultiStatementAllow(true);
        return wallConfig;
    }
}

上面设置filters的地方有点问题,路过的大佬,可以提点建议;

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐