在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

关于Spring中jdbc的模糊查询

2017-2-7 13:41| 发布者: zhangjf| 查看: 485| 评论: 0

摘要: 1、功能需求 对特定的字段进行模糊查询,并以列表形式返回匹配结果 2、解决思路 使用NamedParameterJdbcTemplate类中的query(String sql, SqlParameterSource paramSource, RowMapper rowMapper)方法,其中 ...

1、功能需求

对特定的字段进行模糊查询,并以列表形式返回匹配结果

2、解决思路

使用NamedParameterJdbcTemplate类中的query(String sql, SqlParameterSource paramSource, RowMapper rowMapper)方法,其中sql是查询语句,paramSource是对应查询语句中的参数列表,rowMapper是每一行记录,对应一个对象。

3、发现问题

根据以往的经验(其实很少),模糊匹配就是where 字段 like '%匹配值%'。然后跟NamedParameterJdbcTemplate的占位符相结合,通过冒号(:)加参数名的方式来代表,即:

  1. ......
  2. sql = "... where column like '%:key%'";
  3. paramSource.addValue(key,value);
  4. ......
  5. JdbcTemplate.query(sql,paramSource,rowMapper);
复制代码

匹配的结果是,0(实际上是有满足条件的)。度娘也没有太多办法,只好自己下载spring的源码去debug了。最关键的代码,就是以下这段:

  1. protected PreparedStatementCreator getPreparedStatementCreator(String sql, SqlParameterSource paramSource) {
  2. ParsedSql parsedSql = getParsedSql(sql);
  3. String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
  4. Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null);
  5. List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource);
  6. PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters);
  7. return pscf.newPreparedStatementCreator(params);
  8. }
复制代码

getParsedSql是用来识别sql中参数的名字和统计参数的个数,识别的标准有:name和:{name}两种形式;

substituteNamedParameters是将sql中已识别的参数替换为?占位符,如果参数是一个集合类型的话,会把对象里面的属性遍历出来,并用?代替,变成最后真正使用的sql语句;

buildValueArray是将输入参数的值转化为Object数组;

buildSqlParameterList是将输入参数的名字转化为List;

PreparedStatementCreatorFactory新建一个工厂类;

最后利用newPreparedStatementCreator的方法生成并返回PreparedStatementCreator的实现类。

最后找到问题的根源在,getParsedSql-->NamedParameterUtils.parseSqlStatement-->skipCommentsAndQuotes方法中会自动跳过一些字段,下面就是跳过的开始字符和结束字符的匹配规则。

  1. String[] START_SKIP = new String[] {"'", """, "--", "/*"};
  2. String[] STOP_SKIP = new String[] {"'", """, "n", "*/"};
复制代码

首先,spring是通过识别特殊字符来确定参数的数量的,如“:name”。由于我的:key是放在了单引号'的中间,所以就不能够统计sql中参数的名字和统计参数的个数,因此尽管我的paramSource里面是包含了相应的参数,但程序是不接受的。

4、问题初解决

解决问题的方法,就是sql中不能够包含单引号',那就这样吧

  1. ......
  2. sql = "... where column like :key";
  3. paramSource.addValue(key,"'%"+value+"%'");
  4. ......
复制代码

上面的方法,居然还是不行。

5、问题终解决

原来是不需要添加单引号'的

  1. ......
  2. sql = "... where column like :key";
  3. paramSource.addValue(key,"%"+value+"%");
  4. ......
复制代码

后来才发现,jdbc中的参数化查询,本来就是这样子的:

  1. sql = "... where column like %?%";
复制代码

5、经验总结

其实,很多时候会发现问题的根源是个小问题,但是通过查看源码找到问题,并解决问题的过程,感觉自己就像个侦探,抽丝剥茧,层层深入,最后谜底解开。哈哈哈~ 就是对自己的鼓励吧!!!

来自: http://my.oschina.net/u/1793377/blog/552546

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-7-9 09:26

Copyright 2015-2025 djqfx

返回顶部