一、功能需求java
对特定的字段进行模糊查询,并以列表形式返回匹配结果
spring
二、解决思路sql
使用NamedParameterJdbcTemplate类中的query(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)方法,其中sql是查询语句,paramSource是对应查询语句中的参数列表,rowMapper是每一行记录,对应一个对象。数组
三、发现问题app
根据以往的经验(其实不多),模糊匹配就是where 字段 like '%匹配值%'。而后跟NamedParameterJdbcTemplate的占位符相结合,经过冒号(:)加参数名的方式来表明,即:ui
...... sql = "... where column like '%:key%'"; paramSource.addValue(key,value); ...... JdbcTemplate.query(sql,paramSource,rowMapper);
匹配的结果是,0(其实是有知足条件的)。度娘也没有太多办法,只好本身下载spring的源码去debug了。最关键的代码,就是如下这段:spa
protected PreparedStatementCreator getPreparedStatementCreator(String sql, SqlParameterSource paramSource) { ParsedSql parsedSql = getParsedSql(sql); String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource); Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null); List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource); PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters); return pscf.newPreparedStatementCreator(params); }
getParsedSql是用来识别sql中参数的名字和统计参数的个数,识别的标准有:name和:{name}两种形式;debug
substituteNamedParameters是将sql中已识别的参数替换为?占位符,若是参数是一个集合类型的话,会把对象里面的属性遍历出来,并用?代替,变成最后真正使用的sql语句;code
buildValueArray是将输入参数的值转化为Object数组;对象
buildSqlParameterList是将输入参数的名字转化为List;
PreparedStatementCreatorFactory新建一个工厂类;
最后利用newPreparedStatementCreator的方法生成并返回PreparedStatementCreator的实现类。
最后找到问题的根源在,getParsedSql-->NamedParameterUtils.parseSqlStatement-->skipCommentsAndQuotes方法中会自动跳过一些字段,下面就是跳过的开始字符和结束字符的匹配规则。
String[] START_SKIP = new String[] {"'", "\"", "--", "/*"}; String[] STOP_SKIP = new String[] {"'", "\"", "\n", "*/"};
首先,spring是经过识别特殊字符来肯定参数的数量的,如“:name”。因为个人:key是放在了单引号'的中间,因此就不可以统计sql中参数的名字和统计参数的个数,所以尽管个人paramSource里面是包含了相应的参数,但程序是不接受的。
四、问题初解决
解决问题的方法,就是sql中不可以包含单引号',那就这样吧
...... sql = "... where column like :key"; paramSource.addValue(key,"'%"+value+"%'"); ......
上面的方法,竟然仍是不行。
五、问题终解决
原来是不须要添加单引号'的
...... sql = "... where column like :key"; paramSource.addValue(key,"%"+value+"%"); ......
后来才发现,jdbc中的参数化查询,原本就是这样子的:
sql = "... where column like %?%";
五、经验总结
其实,不少时候会发现问题的根源是个小问题,可是经过查看源码找到问题,并解决问题的过程,感受本身就像个侦探,抽丝剥茧,层层深刻,最后谜底解开。哈哈哈~ 就是对本身的鼓励吧!!!