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\'的這種形式插入。
第一種方法可以成功比較好理解一些,但是第二種就有點想不通了。這里從源代碼看出一點端倪就是會判斷字符串中有沒有轉義字符,而且還會判斷字符串需不需要被括起來。現就了解了這些,有空再深鉆。
轉載于:https://www.cnblogs.com/tuhooo/p/6181623.html
總結
以上是生活随笔為你收集整理的jdbc中如何实现模糊查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 亲测:阿里云的高效云盘真没有声称那么好
- 下一篇: 有人知道比比赞零食为什么那么便宜吗?