MyBatis拦截器动态修改SQL语句及参数值(场景:查询中字段值中特殊字符自动转义)
2014-09-22 17:04
2356 查看
解决问题的场景:执行人名字中含有_ 的,在查询中用_或含有_ 的字段,列表中查不到信息解决问题的思路:获取从MyBatis的mapper Xml文件中,找到原始的Sql语句(条件判断处理已好的SQL),在含有Like的查询字段值里若包含特殊字符,则转义 ,并在查询条件后面添加 " ESCAPE '/'。处理后的Sql语句类似:select * from from syslog where t like '%\_条件值%' " ESCAPE '/' and OPER_REMARK like '%\_条件值%' " ESCAPE '/'关键点:要获取原始SQL ,根据查询条件动态地修改SQL及参数值代码部分:拦截器基础:配置:<plugin interceptor="xxx.mybatis.plugin.PaginationInterceptor"> <property name="dialect" value="oracle" /> <property name="pageSqlId" value=".*ListPage.*" /> <property name="exampleDialect" value="exampleOracle" /> <property name="examplePageSqlId" value="selectByExample" /> </plugin>sqlMapper配置
<select id="getListPage" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from syslog where 1=1 <if test="directoryId != null and directoryId !='' "> and DIRECTORY_ID = #{directoryId} </if> <if test="operRemark != null and operRemark != '' "> and OPER_REMARK LIKE '%' || #{operRemark} || '%' </if>拦截器主体代码:
public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY,DEFAULT_OBJECT_WRAPPER_FACTORY); MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement"); MetaObject metaMappedStatement = MetaObject.forObject(mappedStatement, DEFAULT_OBJECT_FACTORY2,DEFAULT_OBJECT_WRAPPER_FACTORY2);
//调用代码获取原始SQL并将其修改,参数值也
BoundSql boundSql = statementHandler.getBoundSql();//原始sql对象 // 修改参数值 SqlNode sqlNode = (SqlNode) metaMappedStatement .getValue("sqlSource.rootSqlNode");
<span style="white-space:pre"> </span>//修改后的SQL对象 boundSql = PaginationInterceptor.getBoundSql(mappedStatement.getConfiguration(), boundSql.getParameterObject(), sqlNode);获取SQL
public static BoundSql getBoundSql(Configuration configuration,Object parameterObject,SqlNode sqlNode) { DynamicContext context = new DynamicContext(configuration, parameterObject); //DynamicContext context = new DynamicContext(mappedStatement.getConfiguration(), boundSql.getParameterObject()); //mappedStatement.getSqlSource(). sqlNode.apply(context); String countextSql=context.getSql();// System.out.println("context.getSql():"+countextSql); 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 HashMap){ }else{ return sql; } if(!sql.toLowerCase().contains("like")) return sql; //sql=" and OPER_REMARK LIKE '%' || #{operRemark} || '%' \n " +"and OPER_U_NAME LIKE #{operUName} || '%' "; //原始表达式:\s\w+\sLIKE\s('%'\s\|{2})?\s*(#\{\w+\})\s*(\|{2}\s*'%') String reg="\\s\\w+\\sLIKE\\s*('%'\\s*\\|{2}\\s*)?(#\\{\\w+\\})(\\s*\\|{2}\\s*'%')?";//"order\\s+by\\s+.+" Pattern pattern = Pattern.compile(reg,Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(sql); List<String> replaceEscape=new ArrayList<String>(); List<String> replaceFiled=new ArrayList<String>(); while(matcher.find()){ replaceEscape.add(matcher.group()); int n = matcher.groupCount(); for (int i = 0; i <= n; i++) { String output = matcher.group(i); if(2==i&&output!=null) { replaceFiled.add(output.trim()); } } } //sql = matcher.replaceAll(reg+" 1111"); for(String s:replaceEscape) { sql=sql.replace(s, s+" ESCAPE '/' "); } //修改参数 HashMap<String,Object> paramMab=(HashMap)parameterObject; for(String s:replaceFiled) { //sql=sql.replace(s, " ? "); // #{operUName} -->operUName String key=s.replace("#{", "").replace("}", ""); Object val =paramMab.get(key); if(val!=null &&val instanceof String&&(val.toString().contains("%")||val.toString().contains("_"))) { val=val.toString().replaceAll("%", "/%").replaceAll("_", "/_"); paramMab.put(key.toString(), val); } } return sql; }源代码文件如下:
MyBatis拦截器分页与动态修改SQL及其参数值
相关文章推荐
- mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符,可使用本函数来预防数据库攻击。
- 查询语句自动增加序列号、获取字段长度、返回字符在字段中的位置信息、从第几个位置替换字符串
- SQL语句查询结果集中的动态修改案例(临时表+游标)
- sql查询语句(修改表字段)
- SQL语句查询结果集中的动态修改案例(临时表+游标)
- PHP mysqli_real_escape_string()函数--转义 SQL 语句中的特殊字符
- 如何在sql的查询语句中插入特殊字符
- SQL语句查询结果集中的动态修改案例(临时表+游标)
- [原创]通过动态Sql语句,一次性彻底删除或者修改SBO的某个字段对应内容的信息
- 在SQL语句中查询多条记录并把多条记录同一字段的值连接成一个字符并返回的写法
- SQL语句对于多表联合查询重复字段的特殊语法处理
- java用字符串拼接SQL语句的特殊字符转义问题
- ORACLE SQL查询中特殊字符的转义
- sqlserver 修改字段类型,同表查询重复记录sql语句
- mybats 自动生成SQl 语句 修改 查询 添加
- sql语句 查询字段中指定字符之间的数据
- SQL语句查询结果集中的动态修改案例(临时表+游标)
- 用SQL语句修改MSSQL数据库表字段的默认值(downmoon)
- 查询同一表内多字段同时重复记录的SQL语句!
- 动态生成SQL查询条件定制表单及语句的脚本