zoukankan      html  css  js  c++  java
  • MyBatis Like查询处理%_符号

    如果我们数据库中存的字段包含有"%_"这两个like查询的通配符,那么在查询的时候把"%_"当作关键字是查询不出来的,因为mybatis会把这两个字符当作通配符。解决方法是要能加转义字符

    1.定义一个拦截器,如果要查询的字符串中包含"%_"则增加一个转义字符

    @Intercepts({
            @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class,
                    RowBounds.class, ResultHandler.class})})
    public class QueryExecutorInterceptor implements Interceptor {
    
        private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
        private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
        private static final ReflectorFactory DEFAULT_OBJECT_REFLECTOR_FACTORY = new DefaultReflectorFactory();
        private static final String ROOT_SQL_NODE = "sqlSource.rootSqlNode";
    
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            Object parameter = invocation.getArgs()[1];
            MappedStatement statement = (MappedStatement) invocation.getArgs()[0];
            MetaObject metaMappedStatement = MetaObject.forObject(statement, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_OBJECT_REFLECTOR_FACTORY);
            BoundSql boundSql = statement.getBoundSql(parameter);
            if (metaMappedStatement.hasGetter(ROOT_SQL_NODE)) {
                //修改参数值
                SqlNode sqlNode = (SqlNode) metaMappedStatement.getValue(ROOT_SQL_NODE);
                getBoundSql(statement.getConfiguration(), boundSql.getParameterObject(), sqlNode);
            }
            return invocation.proceed();
        }
    
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
    
        @Override
        public void setProperties(Properties properties) {
        }
    
    
        public static BoundSql getBoundSql(Configuration configuration, Object parameterObject, SqlNode sqlNode) {
            DynamicContext context = new DynamicContext(configuration, parameterObject);
            sqlNode.apply(context);
            String countextSql = context.getSql();
            SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
            Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
            String sql = modifyLikeSql(countextSql, parameterObject);
            SqlSource sqlSource = sqlSourceParser.parse(sql, parameterType, context.getBindings());
    
            BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
            for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
                boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
            }
            return boundSql;
        }
    
        public static String modifyLikeSql(String sql, Object parameterObject) {
            if (parameterObject instanceof Map) {
            } else {
                return sql;
            }
            if (!sql.toLowerCase().contains("like"))
                return sql;
            String reg = "\bLIKE\b.*\#\{\b.*\}";
            Pattern pattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
            Matcher matcher = pattern.matcher(sql);
    
            List<String> replaceFiled = new ArrayList<String>();
    
            while (matcher.find()) {
                int n = matcher.groupCount();
                for (int i = 0; i <= n; i++) {
                    String output = matcher.group(i);
                    if (output != null) {
                        String key = getParameterKey(output);
                        if (replaceFiled.indexOf(key) < 0) {
                            replaceFiled.add(key);
                        }
                    }
                }
            }
            //修改参数
            Map<String, Object> paramMab = (Map) parameterObject;
            for (String key : replaceFiled) {
                Object val = paramMab.get(key);
                if (val != null && val instanceof String && (val.toString().contains("%") || val.toString().contains("_"))) {
                    val = val.toString().replaceAll("%", "/%").replaceAll("_", "/_");
                    paramMab.replace(key.toString(), val);
                }
    
            }
            return sql;
        }
    
        private static String getParameterKey(String input) {
            String key = "";
            String[] temp = input.split("#");
            if (temp.length > 1) {
                key = temp[1];
                key = key.replace("{", "").replace("}", "").split(",")[0];
            }
            return key.trim();
        }

    2. 对面的查询mapper like后面要加escape '/'

    <select id="getList" resultMap="MultiResultMap" parameterType="java.util.Map">
            SELECT * FROM SYS_TEST T
            WHERE 1=1
            <if test="_parameter.containsKey('key')">
                AND UPPER(CONCAT(T.ROLE_NAME,T.ROLE_INFO)) LIKE UPPER (CONCAT(CONCAT('%', #{key, jdbcType=VARCHAR}),'%')) ESCAPE '/'
            </if>
        </select>

    最好的做法是可以直接拦截SQL,然后在SQL后面自动加上ESCAPE '/',但还没有找到合适的方法

  • 相关阅读:
    HTML表单
    USB3.0接口传输速度慢
    工作总结
    前台获取时间差--兼容那些事
    多个时间段统计
    【Spring】--OpenSessionInViewFilter 的配置及作用
    【Hibernate】--关联关系映射:继承映射
    【Hibernate】--关联关系映射:多对多映射
    【Spring】--Spring方法注入
    【Hibernate】--关联关系映射:一对多和多对一
  • 原文地址:https://www.cnblogs.com/Gyoung/p/5876632.html
Copyright © 2011-2022 走看看