關于Spring中jdbc的模糊查詢

jopen 8年前發布 | 20K 次閱讀 JDBC Java開發

1、功能需求

    對特定的字段進行模糊查詢,并以列表形式返回匹配結果

2、解決思路

    使用NamedParameterJdbcTemplate類中的query(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)方法,其中sql是查詢語句,paramSource是對應查詢語句中的參數列表,rowMapper是每一行記錄,對應一個對象。

3、發現問題

    根據以往的經驗(其實很少),模糊匹配就是where 字段 like '%匹配值%'。然后跟NamedParameterJdbcTemplate的占位符相結合,通過冒號(:)加參數名的方式來代表,即:

......
sql = "... where column like '%:key%'";
paramSource.addValue(key,value);
......    
JdbcTemplate.query(sql,paramSource,rowMapper);

    匹配的結果是,0(實際上是有滿足條件的)。度娘也沒有太多辦法,只好自己下載spring的源碼去debug了。最關鍵的代碼,就是以下這段:

protected PreparedStatementCreator getPreparedStatementCreator(String sql, SqlParameterSource paramSource) {
    ParsedSql parsedSql = getParsedSql(sql);
    String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
    Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null);
    List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource);
    PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters);
    return pscf.newPreparedStatementCreator(params);
}

    getParsedSql是用來識別sql中參數的名字和統計參數的個數,識別的標準有:name和:{name}兩種形式;

    substituteNamedParameters是將sql中已識別的參數替換為?占位符,如果參數是一個集合類型的話,會把對象里面的屬性遍歷出來,并用?代替,變成最后真正使用的sql語句;

    buildValueArray是將輸入參數的值轉化為Object數組;

    buildSqlParameterList是將輸入參數的名字轉化為List;

    PreparedStatementCreatorFactory新建一個工廠類;

    最后利用newPreparedStatementCreator的方法生成并返回PreparedStatementCreator的實現類。

    最后找到問題的根源在,getParsedSql-->NamedParameterUtils.parseSqlStatement-->skipCommentsAndQuotes方法中會自動跳過一些字段,下面就是跳過的開始字符和結束字符的匹配規則。

String[] START_SKIP = new String[] {"'", "\"", "--", "/*"};
String[] STOP_SKIP = new String[] {"'", "\"", "\n", "*/"};

    首先,spring是通過識別特殊字符來確定參數的數量的,如“:name”。由于我的:key是放在了單引號'的中間,所以就不能夠統計sql中參數的名字和統計參數的個數,因此盡管我的paramSource里面是包含了相應的參數,但程序是不接受的。

4、問題初解決

    解決問題的方法,就是sql中不能夠包含單引號',那就這樣吧

......
sql = "... where column like :key";
paramSource.addValue(key,"'%"+value+"%'");
......

    上面的方法,居然還是不行。

5、問題終解決

    原來是不需要添加單引號'的

......
sql = "... where column like :key";
paramSource.addValue(key,"%"+value+"%");
......

    后來才發現,jdbc中的參數化查詢,本來就是這樣子的:

sql = "... where column like %?%";

    5、經驗總結

    其實,很多時候會發現問題的根源是個小問題,但是通過查看源碼找到問題,并解決問題的過程,感覺自己就像個偵探,抽絲剝繭,層層深入,最后謎底解開。哈哈哈~  就是對自己的鼓勵吧!!!

來自: http://my.oschina.net/u/1793377/blog/552546

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!