一、功能需求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 %?%";
五、經驗總結
其實,不少時候會發現問題的根源是個小問題,可是經過查看源碼找到問題,並解決問題的過程,感受本身就像個偵探,抽絲剝繭,層層深刻,最後謎底解開。哈哈哈~ 就是對本身的鼓勵吧!!!