今天发现一个MySQL驱动包执行in语句的一个bug,也许会有很多人还不知道,那么跟大家分享一下。

驱动包版本:mysql-connector-java-5.1.36.jar

在使用dbutils执行sql语句的时候,遇到这样的sql:

select * from 表名 where 字段名 in (?)

如果你是这样写的,那肯定查询不到你想要的结果,验证此问题只在mysql上存在,如果传进去的是一个字符串,那么你将得到一个这样的一个预编译sql:

select * from 表名 where 字段名 in ('真实值,真实值...');

这样只会查询出在in里面第一个真实值匹配的结果。
下面代码说明
更改前我的代码

List<Long> articleIds = ArticleTag.INSTANCE.findByTagId(tagId);
        StringBuilder sb = new StringBuilder();
        for (Long id : articleIds) {
            sb.append(id + ",");
        }
        String idString = null;
        //去掉末尾的","
        if (sb.length() > 1) {
            idString = sb.substring(0, sb.length() - 1).toString();
        } else {
            return new ArrayList<Article>(0);
        }
        List<Long> ids = getIds("trash = 0 AND status = '" + Article.Status.PUBLISH
                        + "' AND id in (?) ORDER BY id DESC",
                idString);

上面是执行查询的代码,参数idString是一个字符串,getIds()方法调用底层QueryRunner的query();
查询底层实现看下dbutils的关于QueryRunner的query源码(源码太多,挑重点看一下):

                stmt = this.prepareStatement(conn, sql);
                this.fillStatement(stmt, params);
                rs = this.wrap(stmt.executeQuery());
                result = rsh.handle(rs);

在使用fillStatement设置参数的时候,执行下面源码(依然挑重点)

if(!var14) {
    var15 = null;
    parameterAsBytes = new StringBuilder(x.length() + 2);
    parameterAsBytes.append('\'');
    parameterAsBytes.append(x);
    parameterAsBytes.append('\'');
    if(!this.isLoadDataQuery) {
    var16 = StringUtils.getBytes(parameterAsBytes.toString(), this.charConverter, this.charEncoding, this.connection.getServerCharset(), this.connection.parserKnowsUnicode(), this.getExceptionInterceptor());
                            } else {
                                var16 = StringUtils.getBytes(parameterAsBytes.toString());
                        }

我们可以看到底层会将你传递进来的参数加上’’,并没有针对区分,所以SQL语句如上面我们说的in(’真实值,真实值…’)。这就导致了查询数据错误。
网上查询了说传数组进去,仔细想想也不靠谱。后来发现只能将?作为变量拼接进sql才能解决。
更改后代码:

List<Long> articleIds = ArticleTag.INSTANCE.findByTagId(tagId);
        StringBuilder sb = new StringBuilder();
        StringBuffer params = new StringBuffer();
        for (Long id : articleIds) {
            sb.append(id + ",");
            params.append("?,");
        }
        String idString = null;
        String paramsStr = null;
        String[] str = new String[sb.length()];
        //去掉末尾的","
        if (sb.length() > 1) {
            idString = sb.substring(0, sb.length() - 1).toString();
            paramsStr = params.substring(0, params.length() - 1).toString();
            str = idString.split(",");
        } else {
            return new ArrayList<Article>(0);
        }
        List<Long> ids = getIds("trash = 0 AND status = '" + Article.Status.PUBLISH
                        + "' AND id in ("+paramsStr+") ORDER BY id DESC",
                str);

将?也作为变量根据参数的个数动态拼接到sql里,这样问题就解决了,当然这也只是我的做法,如果大家有更好的做法,希望留言互相讨论,也希望这个bug能够修复。

转载地址:河流博客

关于mysql驱动包的in语句的bug的更多相关文章

  1. Oozie安装时放置Mysql驱动包的总结(网上最全)

    不多说,直接上干货! 对于在oozie里放置Mysql驱动包的总结 根据网上的参考以及我个人经验安装的使用 (1)放一份到$OOZIE_HOME/libext下 (是 mysql-connector- ...

  2. JDBC-Web项目导入mysql驱动包路径-Eclipse & Myeclipse

    初学JAVA,很多都不懂,开始听老师说导入数据库驱动包的时候是: 右键项目 -> Properties -> Java Build Path -> 右侧选项卡选择Libraries ...

  3. mysql驱动包

    mysql驱动包和源码下载地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java 下载 mysql-connector-jav ...

  4. 使用Maven导入MySQL驱动包遇到的问题

    问题描述 今天在使用Maven导入MySQL数据库驱动包依赖后,直接运行项目,出现错误. java.sql.SQLException: No suitable driver found for jdb ...

  5. pycharm安装mysql驱动包

    新的环境配置pycharm的项目时,发现pycharm不能连接到mysql数据库.由于安了java环境但是还没配置相关的库,并且jetbrains家的IDE一般都是java写的,于是猜想可能是java ...

  6. 各种版本mysql驱动包下载地址

    http://central.maven.org/maven2/mysql/mysql-connector-java/

  7. JSP连接mysql 驱动包

    360网盘 https://yunpan.cn/cPxT6CV9Kydyb  访问密码 1df9

  8. mysql驱动包下载

  9. 如何实现在Eclipse导入MySQL驱动包

    1 右键项目->Properties->Java Build Path->Libraries->Add External JARs...->mysql-connector ...

随机推荐

  1. HTTP协议----请求方法和状态码

    现在广泛使用的是HTTP/1.1版本,发布于1997年. 理解HTTP协议,首先从请求开始,比如: POST /form/entry HTTP/1.1 格式为: 请求方法 URI 协议版本 请求方法: ...

  2. Leetcode 28——Implement strStr()

    Implement strStr(). Return the index of the first occurrence of needle in haystack, or -1 if needle ...

  3. JavaScript(第二天)【语法,变量】

    一.语法构成 区分大小写 ECMAScript中的一切,包括变量.函数名和操作符都是区分大小写的.例如:text和Text表示两种不同的变量.   标识符 所谓标识符,就是指变量.函数.属性的名字,或 ...

  4. C语言的第一次作业总结

    PTA实验作业 题目一:温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1.实验代码: ...

  5. 2017-2018-1 20155306 《信息安全系统设计基础》Mybash的实现

    2017-2018-1 20155306 <信息安全系统设计基础>Mybash的实现 要求: 使用fork,exec,wait实现mybash 写出伪代码,产品代码和测试代码 发表知识理解 ...

  6. Bate敏捷冲刺每日报告--day2

    1 团队介绍 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(267),蔡凯峰(285)  Git链接:https://github.com/WHUSE2017/C-team 2 ...

  7. RxSwift(一)

    文/iOS_Deve(简书作者) 原文链接:http://www.jianshu.com/p/429b5160611f 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者" ...

  8. 函数式编程之foldLeftViaFoldRight

    问题来自 Scala 函数式编程 一书的习题, 让我很困扰, 感觉函数式编程有点神学的感觉.后面看懂之后, 又觉得函数式编程所提供的高阶抽象是多么的强大. 这个问题让我发呆了好久, 现在把自己形成的想 ...

  9. SpringMVC之数据传递一

    之前的博客中也说了,mvc中数据传递是最主要的一部分,从url到Controller.从view到Controller.Controller到view以及Controller之间的数据传递.今天主要学 ...

  10. angular2 学习笔记 ( server-side rendering, angular universal, 服务端渲染 )

    更新 : 2018-01-10  大半年过去了依然没有做 server side render 的冲动,但是一直有关注这方便的做法. 今天领悟了一些道理, 这里做个记入. server side re ...