情况如何

再利用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. rados命令

    chen@admin-node:/etc/ceph$ rados --help usage: rados [options] [commands] POOL COMMANDS lspools list ...

  2. Jquery EasyUI使用总结(一)

    1,弹出Iframe,新窗口 //打开编辑页面要加载的数据 function ShowDialog(id, url, width, height, onLoadFunc) { $("#&qu ...

  3. C++程序设计(二)

    1. 类 class CRectangle { public: int w, h; void Init( int w_, int h_ ) { w = w_; h = h_; } int Area() ...

  4. iOS 1-2年经验面试参考题

    Model层: 数据持久化存储方案有哪些? 沙盒的目录结构是怎样的?各自一般用于什么场合? SQL语句问题:inner join.left join.right join的区别是什么? SQLite的 ...

  5. CentOS修改mysql 用户root的密码并允许远程登录

    第一步:用帐号登录mysql[root@CentOs5 ~]# mysql -u root -p 第二步:改变用户数据库mysql> use mysql 第三步:修改密码,记得密码要用passw ...

  6. Synchronized 个人深解

      1.synchronized方法相当于synchronized(this)      Synchronized 方法是锁的当前对象,同一个对象的2个synchronized方法被2个线程调用会发生 ...

  7. Sql Server 性能优化之包含列

    导读:数据数优化查询一直是个比较热门的话题,小生在这方面也只能算是个入门生.今 天我们就讲下数据库包含列这个一项的作用及带来的优化效果 引用下MSDN里面的一段解释: 当查询中的所有列都作为键列或非键 ...

  8. [BS-29] 给UIView添加背景图片

    给UIView添加背景图片 //默认情况下只能设置UIView的背景颜色,不能给UIView设置背景图片,但通过绘图知识可以做到 - (void)drawRect:(CGRect)rect { [su ...

  9. git如何使用 svn如何使用

    git和svn是2款常用的版本控制系统. git 的功能: 1.从服务器上克隆完整的Git仓库(包括代码和版本信息)到单机上. 也就是说自己机器上有一个git仓库. 这和svn是不同的,svn是没有本 ...

  10. 20145320 《Java程序设计》第8周学习总结

    20145320 <Java程序设计>第8周学习总结 教材学习内容总结 15.1日志 java.util.logging包提供了日志功能相关类与接口,不必额外配置日志组件,就可以在标准ja ...