Springにおけるjdbcのボケに関するお問い合わせ


1、機能需要
    特定のフィールドに対してあいまいなクエリーを行い、リスト形式でマッチ結果を返します。
2、考え方を解決する
    NamedParameterJdbcTemplateクラスのquery(String sql、Sql ParameterSource paramSource、RowMapper<T>rowMapper)を使って、ここでsqlは照会文で、paramSourceはクエリー文のパラメータリストで、rowMapperは一行ごとに対象を記録します。
3、問題を発見する
    これまでの経験によると、ぼかしマッチングはwhereフィールドlike'%マッチ値%です。NamedParameter JdbcTemplateのプレースホルダと結合して、コロン(:)に参数名を加えることによって代表されます。
......
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);
}
    get PasedSqlはsqlの中のパラメータの名前と統計パラメータの個数を識別するために用いられています。識別の基準は、nameと「{name}」の二種類です。
    substitute NamedParametersはsqlで認識されているパラメータを置換しますか?プレースホルダは、パラメータがセットタイプの場合、オブジェクトの中の属性を遍歴して使用しますか?代わりに、最後に本当に使うsql文になります。
    buildValueArayは入力パラメータの値をObject配列に変換します。
    buildSql ParameterListは入力パラメータの名前をListに変換します。
    PreparedSttement Creator Factoryは新しい工場種類を作ります。
    最後に、newPreparedStartement Creatorの方法でPreparedSttement Creatorの実現クラスを生成し、リターンします。
    最後に問題の根源を見つけたのは、getParssedSql-->NamedParameterUtils.parseSql Sttement-->skyComments AndQuotesメソッドでは自動的にいくつかのフィールドをスキップします。以下はスキップの開始文字と終了文字のマッチングルールです。
String[] START_SKIP = new String[] {"'", "\"", "--", "/*"};
String[] STOP_SKIP = new String[] {"'", "\"", "
", "*/"};
    まず、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、経験のまとめ
    実は、多くの時問題の根源は小さい問題だと発見しますが、ソースコードを調べて問題を見つけて、問題を解決する過程は自分が探偵のように感じられます。ハハハ 自分への励ましですよね!