文档章节

关于Spring中jdbc的模糊查询

33号小人物
 33号小人物
发布于 2015/12/28 22:29
字数 745
阅读 2123
收藏 2

1、功能需求

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

2、解决思路

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

3、发现问题

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

......
sql = "... where column like '%:key%'";
paramSource.addValue(key,value);
......    
JdbcTemplate.query(sql,paramSource,rowMapper);

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

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}两种形式;

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

    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里面是包含了相应的参数,但程序是不接受的。

4、问题初解决

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

......
sql = "... where column like :key";
paramSource.addValue(key,"'%"+value+"%'");
......

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

5、问题终解决

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

......
sql = "... where column like :key";
paramSource.addValue(key,"%"+value+"%");
......

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

sql = "... where column like %?%";

    5、经验总结

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

© 著作权归作者所有

共有 人打赏支持
33号小人物
粉丝 1
博文 3
码字总数 2040
作品 0
广州
高级程序员
私信 提问
SpringBoot实战(四)之使用JDBC和Spring访问数据库

这里演示的是h2databse示例,所以简单的介绍普及下h2database相关知识 H2数据库是一个开源的关系型数据库。 H2是一个嵌入式数据库引擎,采用java语言编写,不受平台的限制,同时H2提供了一个...

youcongtech
08/03
0
0
Spring之jdbc Template实现CRUD操作

Spring为各种持久化技术都提供了简单操作的模板回调。比如jdbc、hibernate、Mybatis以及JPA等。 这里我们就以JDBC为例,看看JDBC template怎么实现CRUD操作。 JdbcTemplate主要提供以下几类方...

Java攻城玩家
05/31
0
0
Spring boot 中自定义JpaRepository使用

普通JpaRepository类 JpaRepository一般的筛选查询,均可以通过的形式解决,总的很好用,但是总有一部分的业务查询是需要JpaRepository不能解决的。这个时候,就需要在此基础上面增加自定义的...

亚林瓜子
08/10
0
0
Spring框架笔记(二十四)——Spring中的JDBC的两种使用方式

为了使 JDBC 更加易于使用, Spring 在 JDBC API 上定义了一个抽象层, 以此建立一个 JDBC 存取框架. 作为 Spring JDBC 框架的核心, JDBC 模板的设计目的是为不同类型的 JDBC 操作提供模板方法...

HappyBKs
2015/08/26
0
0
为什么Java大神,都在看Spring Boot和Spring Cloud的书?

如果你是一名Java开发人员,并且最近正打算学习Spring Boot和Spring Cloud框架并寻找一些关于它们的最好的书籍,那么,你今天就来对地方了。 本文,我们将讨论一些学习Spring Boot和Spring ...

Java小铺
09/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

2018年终盘点:区块链真的结束了吗?

2018 年,大家依旧期待区块链出现“杀手级”应用,然而到了年关,终究还是没有。既然没有出现,只能认为“神功”尚未练成,但是这一年也没有虚度,让大家再一次领教了这个领域的跌宕起伏。 ...

酒逢知己千杯少
4分钟前
0
0
社交软件系统ThinkSNS+默认配置信息说明

感谢大家一直以来对社交软件系统ThinkSNS的关注,ThinkSNS Plus社交系统一直在不断优化完善。ThinkSNS Plus 本次于2018年12月3日更新发布。 本次重要更新说明如下: 1.优化默认配置信息,服务...

ThinkSNS账号
6分钟前
0
0
阿里云文件存储(NAS)助力业务系统承载双十一尖峰流量

2018天猫双11全球狂欢节,全天成交额再次刷新纪录达到2135亿元,其中总成交额在开场后仅仅用了2分05秒即突破100亿元,峰值的交易量达到惊人的高度,背后离不开阿里云大数据计算和存储能力的支...

阿里云官方博客
8分钟前
0
0
Frost & Sullivan权威报告:阿里云再次领跑云WAF大中华区市场

近日,国际权威分析机构Frost & Sullivan 针对Web应用防火墙(简称“WAF”)领域发布了《2017年亚太区Web应用防火墙市场报告》,阿里云以市场占有率45.8%的绝对优势连续两年领跑大中华区云WAF...

阿里云云栖社区
8分钟前
0
0
Axios使用拦截器全局处理请求重试

Axios拦截器 Axios提供了拦截器的接口,让我们能够全局处理请求和响应。Axios拦截器会在Promise的then和catch调用前拦截到。 请求拦截示例 axios.interceptors.request.use(function (conf...

kisshua
12分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部