關於Spring中jdbc的模糊查詢

一、功能需求java

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

二、解決思路sql

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

三、發現問題app

    根據以往的經驗(其實不多),模糊匹配就是where 字段 like '%匹配值%'。而後跟NamedParameterJdbcTemplate的佔位符相結合,經過冒號(:)加參數名的方式來表明,即:ui

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

    匹配的結果是,0(其實是有知足條件的)。度娘也沒有太多辦法,只好本身下載spring的源碼去debug了。最關鍵的代碼,就是如下這段:spa

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}兩種形式;debug

    substituteNamedParameters是將sql中已識別的參數替換爲?佔位符,若是參數是一個集合類型的話,會把對象裏面的屬性遍歷出來,並用?代替,變成最後真正使用的sql語句;code

    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裏面是包含了相應的參數,但程序是不接受的。

四、問題初解決

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

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

    上面的方法,竟然仍是不行。

五、問題終解決

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

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

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

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

    五、經驗總結

    其實,不少時候會發現問題的根源是個小問題,可是經過查看源碼找到問題,並解決問題的過程,感受本身就像個偵探,抽絲剝繭,層層深刻,最後謎底解開。哈哈哈~  就是對本身的鼓勵吧!!!

相關文章
相關標籤/搜索