jdbc中如何实现模糊查询
情况如何
再利用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中如何实现模糊查询的更多相关文章
- JDBC_14_使用JDBC工具类实现模糊查询
使用JDBC工具类实现模糊查询 代码: import java.sql.*; /** * 模糊查询 * 测试DBUtils */ public class JDBCTest09 { public st ...
- MySQL中使用Like模糊查询太慢
问题:明明建立了索引,为何Like模糊查询速度还是特别慢? Like是否使用索引? 1.like %keyword 索引失效,使用全表扫描.但可以通过翻转函数+like前模糊查询+建立翻转函数索 ...
- WINFORM中的COMBOX模糊查询
有的时候下拉框中的元素过多不好查询,可以考虑进行模糊过滤查询. 在类文件的designer.cs中找到定义combox的模块,加入以下两行代码即可: this.combox.AutoCompleteM ...
- js实现table中前端搜索(模糊查询)
项目中用到js前端搜索功能,根据 姓名或姓名 进行 搜索,实现方法如下,遍历table所有行中的某列,符合条件则置tr为display:'',不满足条件置tr为display:none. 代码如下: ...
- Mysql中的like模糊查询
MySql的like语句中的通配符:百分号.下划线和escape %代表任意多个字符 _代表一个字符 escape,转义字符后面的%或_,使其不作为通配符,而是普通字符匹配 数据库数据如下: 1. ...
- C# ADO.NET中设置Like模糊查询的参数
ADO.NET进行参数化时会自动将参数值包含在单引号中,除了特殊需求,最好不要自己手动添加单引号.ADO.NET中识别参数标识是使用符号@,如果在SQL语句中将参数标识放在单引号中,单引号中的参数标识 ...
- 关于SQL查询语句中的LIKE模糊查询的解释
LIKE语句的语法格式为: select * from 表名 where 字段名 like 对应值(字符串) 注:主要是针对字符型字段的,它的作用是在一个字符型字段列中检索包含对应字符串的. 下面列举 ...
- Jquery如何序列化form表单数据为JSON对象 C# ADO.NET中设置Like模糊查询的参数 从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值 jquery调用iframe里面的方法 Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件 设计模式之简单工厂模式(C#语言描述)
jquery提供的serialize方法能够实现. $("#searchForm").serialize();但是,观察输出的信息,发现serialize()方法做的是将表单中的数 ...
- ibatis中使用like模糊查询
select * from table1 where name like '%#name#%' 两种有效的方法: 1) 使用$代替#.此种方法就是去掉了类型检查,使用字符串连接,不过可能会有sql注入 ...
随机推荐
- 一道打印M的面试题
public class Demo { /** * 平面图形题(二维数组) */ public static void main(String[] args) { int num = 25; int ...
- jwt refresh token
$app->post('auth/refresh-token', ['middleware' => 'jwt.refresh', function() { try { $old_token ...
- LINUX VI 常用命令
vi 打开或新建 vi filename 打开或新建文件 并将光标置于第一行首 光标 ) 光标移至句尾 ( 光标移至句首 屏幕翻滚类命令 Ctrl+u 向文件首翻半屏 Ctrl+d 向文件尾翻半屏 ...
- 转:EntityFramework查询--联合查询(Join,GroupJoin)
首先我们先看一下Join public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this ...
- Java复习笔记--java中this 关键字
Java中this关键字,this可以调用类的成员变量和成员方法,this还可以调用类中的构造方法.使用这种方式值得注意的是, 只可以在无参构造方法中的第一句使用this关键字调用有参构造方法. pu ...
- Java提高篇——equals()方法和“==”运算符
equals() 超类Object中有这个equals()方法,该方法主要用于比较两个对象是否相等.该方法的源码如下: public boolean equals(Object obj) { retu ...
- VMware简介
VMware(中文名威睿”) 虚拟机软件,是全球桌面到数据中心虚拟化解决方案的领导厂商.VMware vSphere 是VMware 的一个虚拟化产品,它包括vCenter,ESX Server,ES ...
- C#.NET序列化XML、JSON、二进制微软自带DLL与newtonsoft(json.net)
序列化是将对象转换成另一种格式(XML.json.二进制byte[]) JSON序列化 .NET中有三种常用的JSON序列化的类,分别是: Newtonsoft.Json.JsonConvert类(推 ...
- Simple JavaScript Inheritance--一个极简JS面向对象-类库
面向对象 面向对象思想的几个重要特征(针对类的要求): 抽象-封装.信息隐藏(将内部实现的方法和数据隐藏, 定义开放的接口) 继承-子类可以使用父类的资源,并可以定制自己的资源, 资源包括方法和数据 ...
- 写在开始编写Java之前(1)——Java的跨平台性
Java语言之所以比C语言更加实用 是有原因的 Java的一个重要的特点——跨平台性 无论是哪个平台,如Windows.Linus还是Mac系统 Java的语法都是一样的 这个要比C语言用处要广 因为 ...