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