zoukankan      html  css  js  c++  java
  • mybatis拦截器修改sql重新set后不生效?

    利用mybatis拦截器做数据权限管理,拦截sql并分析、修改然后重新set。然而有的生效有的不生效。控制台打印的信息表示所有的sql都是修改成功的,那么问题在于重新set的方法。

    一开始用的方法是这个:

    private void setCurrentSql(Invocation invo, String sql) {
    MappedStatement mappedStatement = getMappedStatement(invo);
    Object[] args = invo.getArgs();
    Object paramObj = args[PARAM_OBJ_INDEX];
    BoundSql boundSql = mappedStatement.getBoundSql(paramObj);
    ReflectUtil.setFieldValue(boundSql, "sql", sql);
    }

    通过反射去修改boundSql的sql属性的值,但是有问题。
    后来改用这个方法:
    private void setCurrentSql(Invocation invo, String sql) {
    BoundSql boundSql = getBoundSql(invo);
    List<ParameterMapping> parameterMappings = boundSql.
    getParameterMappings();
    Object paramObj = boundSql.getParameterObject();
    MappedStatement mappedStatement = getMappedStatement(invo);
    Configuration configuration = mappedStatement.getConfiguration();
    BoundSql newBoundSql = new BoundSql(configuration, sql,
    parameterMappings, paramObj);
    for (ParameterMapping parameterMapping : parameterMappings) {
    String prop = parameterMapping.getProperty();
    if (boundSql.hasAdditionalParameter(prop)) {
    Object param = boundSql.getAdditionalParameter(prop);
    newBoundSql.setAdditionalParameter(prop, param);
    }
    }

    BoundSqlSource newSqlSource = new BoundSqlSource(newBoundSql);
    MappedStatement newMappedStatement = copyFromMappedStatement(
    mappedStatement, newSqlSource);
    Object[] args = invo.getArgs();
    args[MAPPED_STATEMENT_INDEX] = newMappedStatement;
    }

    问题解决。还有一种方法,看起来更简洁:
    private void setCurrentSql(Invocation invo, String sql) {
    MappedStatement mappedStatement = getMappedStatement(invo);
    Object[] args = invo.getArgs();
    Object paramObj = args[PARAM_OBJ_INDEX];
    BoundSql boundSql = mappedStatement.getBoundSql(paramObj);
    BoundSqlSource boundSqlSource = new BoundSqlSource(boundSql);
    MappedStatement newMappedStatement = copyFromMappedStatement(
    mappedStatement, boundSqlSource);
    MetaObject metaObject = MetaObject.forObject(newMappedStatement,
    new DefaultObjectFactory(), new DefaultObjectWrapperFactory(),
    new DefaultReflectorFactory());
    metaObject.setValue("sqlSource.boundSql.sql", sql);
    args[MAPPED_STATEMENT_INDEX] = newMappedStatement;
    }

    上面用到的方法getMappedStatement:
    private MappedStatement getMappedStatement(Invocation invo) {
    Object[] args = invo.getArgs();
    Object mappedStatement = args[MAPPED_STATEMENT_INDEX];
    return (MappedStatement) mappedStatement;
    }
    私有内部类BoundSqlSource:
    private class BoundSqlSource implements SqlSource {

    private BoundSql boundSql;

    private BoundSqlSource(BoundSql boundSql) {
    this.boundSql = boundSql;
    }

    @Override
    public BoundSql getBoundSql(Object parameterObject) {
    return boundSql;
    }
    }

    另外还有:
    private static final int MAPPED_STATEMENT_INDEX = 0;
    private static final int PARAM_OBJ_INDEX = 1;
    龙门之桐,高百尺而无枝,其根半死半生。
  • 相关阅读:
    一个关于git push失败的解决方案
    TensorFlow学习笔记 速记2 报错:failed call to cuDevicePrimaryCtxRetain: CUDA_ERROR_INVALID_DEVICE
    Maven父子工程,子项目变灰,提示该项目已被移除出maven父工程
    mysql模糊查询1,11,111用逗号(其他符号)拼接的相似字符串
    如何查看服务器对外的IP
    用navcat编写定时任务调用存储过程
    如何使用jenkins部署maven父子工程
    服务网关ZuulFilter过滤器--pre/post/error的用法(校验请求信息,获取路由后的请求/响应信息,处理服务网关异常)
    服务网关ZuulFilter过滤器--如何解决跨域请求中的OPTIONS请求
    如何获取jar包中resource下的文件
  • 原文地址:https://www.cnblogs.com/longmenzhitong/p/11271909.html
Copyright © 2011-2022 走看看