情况如何

再利用jdbc执行sql语句的时候,对于其他的句子的执行没什么太大的问题:加上占位符,然后设置占位符的值。

但是在模糊查询的时候,一直都写不对,这里提供了两种可选的解决办法,以供参考。

解决方法

第一种:

String sql = "select studentname, age, phone, address, other from customer"
                + " where studentname like ? ";
pstmt = conn.prepareStatement(sql);
// 设定参数
pstmt.setString(1, "%" + customername + "%" );       
// 获取查询的结果集           
rs = pstmt.executeQuery();

第二种:

百分号直接写在sql语句中

String sql = "select customercode, customername, phone, address, relationman, other from customer"
                + " where customername like \"%\"?\"%\" ";
pstmt = conn.prepareStatement(sql);           
// 设定参数
pstmt.setString(1, customername);       
// 获取查询的结果集           
rs = pstmt.executeQuery();

为什么会这样?

得研究一下PreparedStatement是如何来处理占位符的。

在PresparedStatement中的setString()方法中有如下的一段代码:

public void setString(int parameterIndex, String x) throws SQLException {
    synchronized (checkClosed().getConnectionMutex()) {
        // 如果x是空的话,就直接调用另外的方法
        if (x == null) {
            setNull(parameterIndex, Types.CHAR);
        } else {
            checkClosed();

// 获得待插入的字符串的长度
            int stringLength = x.length();

if (this.connection.isNoBackslashEscapesSet()) {
                // Scan for any nasty chars

// 判断字符串中是否需要进行转义的字符
                boolean needsHexEscape = isEscapeNeededForString(x, stringLength);

// 如果x里面没有需要转义的字符串
                if (!needsHexEscape) {
                    byte[] parameterAsBytes = null;

StringBuilder quotedString = new StringBuilder(x.length() + 2);

// 直接就以字符串的形式加入到串中
                    quotedString.append('\'');
                    quotedString.append(x);
                    quotedString.append('\'');

if (!this.isLoadDataQuery) {
                        parameterAsBytes = StringUtils.getBytes(quotedString.toString(), this.charConverter, this.charEncoding,
                                this.connection.getServerCharset(), this.connection.parserKnowsUnicode(), getExceptionInterceptor());
                    } else {
                        // Send with platform character encoding
                        parameterAsBytes = StringUtils.getBytes(quotedString.toString());
                    }

setInternal(parameterIndex, parameterAsBytes);
                } else {
                    byte[] parameterAsBytes = null;

if (!this.isLoadDataQuery) {
                        parameterAsBytes = StringUtils.getBytes(x, this.charConverter, this.charEncoding, this.connection.getServerCharset(),
                                this.connection.parserKnowsUnicode(), getExceptionInterceptor());
                    } else {
                        // Send with platform character encoding
                        parameterAsBytes = StringUtils.getBytes(x);
                    }

setBytes(parameterIndex, parameterAsBytes);
                }

return;
            }

String parameterAsString = x;
            boolean needsQuoted = true;

if (this.isLoadDataQuery || isEscapeNeededForString(x, stringLength)) {
                needsQuoted = false; // saves an allocation later

StringBuilder buf = new StringBuilder((int) (x.length() * 1.1));

buf.append('\'');

//
                // Note: buf.append(char) is _faster_ than appending in blocks, because the block append requires a System.arraycopy().... go figure...
                //
                // 如果需要转义则遍历需要转义的字符
                for (int i = 0; i < stringLength; ++i) {
                    char c = x.charAt(i);

switch (c) {
                        case 0: /* Must be escaped for 'mysql' */
                            buf.append('\\');
                            buf.append('0');

break;

case '\n': /* Must be escaped for logs */
                            buf.append('\\');
                            buf.append('n');

break;

case '\r':
                            buf.append('\\');
                            buf.append('r');

break;

case '\\':
                            buf.append('\\');
                            buf.append('\\');

break;

case '\'':
                            buf.append('\\');
                            buf.append('\'');

break;

case '"': /* Better safe than sorry */
                            if (this.usingAnsiMode) {
                                buf.append('\\');
                            }

buf.append('"');

break;

case '\032': /* This gives problems on Win32 */
                            buf.append('\\');
                            buf.append('Z');

break;

case '\u00a5':
                        case '\u20a9':
                            // escape characters interpreted as backslash by mysql
                            if (this.charsetEncoder != null) {
                                CharBuffer cbuf = CharBuffer.allocate(1);
                                ByteBuffer bbuf = ByteBuffer.allocate(1);
                                cbuf.put(c);
                                cbuf.position(0);
                                this.charsetEncoder.encode(cbuf, bbuf, true);
                                if (bbuf.get(0) == '\\') {
                                    buf.append('\\');
                                }
                            }
                            // fall through

default:
                            buf.append(c);
                    }
                }

buf.append('\'');

parameterAsString = buf.toString();
            }

byte[] parameterAsBytes = null;

if (!this.isLoadDataQuery) {
                if (needsQuoted) {
                    parameterAsBytes = StringUtils.getBytesWrapped(parameterAsString, '\'', '\'', this.charConverter, this.charEncoding,
                            this.connection.getServerCharset(), this.connection.parserKnowsUnicode(), getExceptionInterceptor());
                } else {
                    parameterAsBytes = StringUtils.getBytes(parameterAsString, this.charConverter, this.charEncoding, this.connection.getServerCharset(),
                            this.connection.parserKnowsUnicode(), getExceptionInterceptor());
                }
            } else {
                // Send with platform character encoding
                parameterAsBytes = StringUtils.getBytes(parameterAsString);
            }

setInternal(parameterIndex, parameterAsBytes);

this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.VARCHAR;
        }
    }
}

protected final void setInternal(int paramIndex, byte[] val) throws SQLException {
    synchronized (checkClosed().getConnectionMutex()) {

int parameterIndexOffset = getParameterIndexOffset();

checkBounds(paramIndex, parameterIndexOffset);

this.isStream[paramIndex - 1 + parameterIndexOffset] = false;
        this.isNull[paramIndex - 1 + parameterIndexOffset] = false;
        this.parameterStreams[paramIndex - 1 + parameterIndexOffset] = null;
        this.parameterValues[paramIndex - 1 + parameterIndexOffset] = val;
    }
}

在setString()方法中,字符串会变为\'string\'的这种形式插入。

第一种方法可以成功比较好理解一些,但是第二种就有点想不通了。这里从源代码看出一点端倪就是会判断字符串中有没有转义字符,而且还会判断字符串需不需要被括起来。现就了解了这些,有空再深钻。

jdbc中如何实现模糊查询的更多相关文章

  1. JDBC_14_使用JDBC工具类实现模糊查询

    使用JDBC工具类实现模糊查询 代码: import java.sql.*; /** * 模糊查询 * 测试DBUtils */ public class JDBCTest09 { public st ...

  2. MySQL中使用Like模糊查询太慢

    问题:明明建立了索引,为何Like模糊查询速度还是特别慢? Like是否使用索引? 1.like %keyword    索引失效,使用全表扫描.但可以通过翻转函数+like前模糊查询+建立翻转函数索 ...

  3. WINFORM中的COMBOX模糊查询

    有的时候下拉框中的元素过多不好查询,可以考虑进行模糊过滤查询. 在类文件的designer.cs中找到定义combox的模块,加入以下两行代码即可: this.combox.AutoCompleteM ...

  4. js实现table中前端搜索(模糊查询)

    项目中用到js前端搜索功能,根据 姓名或姓名 进行 搜索,实现方法如下,遍历table所有行中的某列,符合条件则置tr为display:'',不满足条件置tr为display:none. 代码如下: ...

  5. Mysql中的like模糊查询

    MySql的like语句中的通配符:百分号.下划线和escape %代表任意多个字符 _代表一个字符 escape,转义字符后面的%或_,使其不作为通配符,而是普通字符匹配   数据库数据如下: 1. ...

  6. C# ADO.NET中设置Like模糊查询的参数

    ADO.NET进行参数化时会自动将参数值包含在单引号中,除了特殊需求,最好不要自己手动添加单引号.ADO.NET中识别参数标识是使用符号@,如果在SQL语句中将参数标识放在单引号中,单引号中的参数标识 ...

  7. 关于SQL查询语句中的LIKE模糊查询的解释

    LIKE语句的语法格式为: select * from 表名 where 字段名 like 对应值(字符串) 注:主要是针对字符型字段的,它的作用是在一个字符型字段列中检索包含对应字符串的. 下面列举 ...

  8. Jquery如何序列化form表单数据为JSON对象 C# ADO.NET中设置Like模糊查询的参数 从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值 jquery调用iframe里面的方法 Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件 设计模式之简单工厂模式(C#语言描述)

    jquery提供的serialize方法能够实现. $("#searchForm").serialize();但是,观察输出的信息,发现serialize()方法做的是将表单中的数 ...

  9. ibatis中使用like模糊查询

    select * from table1 where name like '%#name#%' 两种有效的方法: 1) 使用$代替#.此种方法就是去掉了类型检查,使用字符串连接,不过可能会有sql注入 ...

随机推荐

  1. 【iCore3 双核心板】例程二十三:LAN_HTTP实验——网页服务器

    实验指导书及代码包下载: http://pan.baidu.com/s/1getgyKr iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...

  2. 推荐《HeadFirst设计模式》

    相对于国内初版的<大话设计模式>,HeadFirst真的是更好的选择,虽然看起来很厚.很吓人,但对于初学者而言浅显易懂.直击要点,即使对设计模式熟悉的同学去读这本书相信也有很大的收获.用了 ...

  3. JS 的trim()

    去除字符串左右两端的空格,在vbscript里 可  用 trim.ltrim 或 rtrim,但 js 却没有这 3个 内置方法,需 手工编写.下面的实现方法  用到 正则表达式,效率不错, 把 三 ...

  4. 《Linux内核设计与实现》CHAPTER5阅读梳理

    <Linux内核设计与实现>CHAPTER5阅读梳理 [学习时间:2.5hours] [学习内容:系统调用的概念.功能及实现:系统调用的创建和使用方法] CHAPTER5 系统调用 1.系 ...

  5. java 使用 poi 解析excel

    背景: web应用经常需要上传文件,有时候需要解析出excel中的数据,如果excel的格式没有问题,那就可以直接解析数据入库. 工具选择: 目前jxl和poi可以解析excel,jxl很早就停止维护 ...

  6. Android流畅度测试

    Android流畅度测试 测试方法一:系统自带-开发者模式 测试方法二:FPS Meter测试安卓帧数 H5页面加载速度:window.performance.timing 测试方法一:系统自带-开发 ...

  7. php日期,时间相关知识整理

    unix 时间戳:从1970年1月1日0点开始到当前时间所经过的秒数. 1.将日期转换为UNIX时间戳 mktime():可以自动校正越界的输入 原型 : mktime(hour,minute,sec ...

  8. The type XXX cannot be resolved. It is indirectly referenced from required .class files错误.....

    遇到The type XXX cannot be resolved. It is indirectly referenced from required .class files错误.....,查找的 ...

  9. 1046: 最小的K个数

    1046: 最小的K个数 时间限制: 1 Sec  内存限制: 128 MB提交: 233  解决: 200[提交][状态][讨论版] 题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1 ...

  10. 设计模式_11_原型模式(prototype)深拷贝、浅拷贝

    设计模式_11_原型模式(prototype) 浅拷贝: package designPatternOf23; /** * 定义:用原型实例,指定创建对象的种类,并通过拷贝这些原型创建新的对象 * P ...