転送します。https://www.cnblogs.com/mytzq/p/9321526.html
動的SQLは、MyBatisのの主な特徴の一つです。渡されたマッパーXMLで定義されたパラメータの後、MyBatisのは、動的にクエリの前に解決されます。
MyBatisの2つのサポート動的SQL構文を提供します:#{}、$ {}。
t_userユーザ名= '$ {ユーザー名}' から選択*;
選択* t_userから場所名=#{ユーザー名}。
ユーザ名パラメータ受け渡しが一致して、両方の実装の結果は同じであるが、動的SQL構文解析段階における2つのハンドルは同じではありません。
1、#{}
これは、パラメーター・マーカー、プレースホルダでパラメータセクションをJDBCプリペアドステートメントに解決(準備書)?代わりに。動的に解決します。
t_userユーザー名から選択* =?;
渡された引数は必須検査と保安検査のPreparedStatementメソッドを渡し、最後に渡された正当な文字列としてします。
2、$ {}
アリスに渡されたパラメータは、最終処理結果が次のようにしている場合にのみ、単純な文字列置換を行うこのように、それは、変数置換の動的SQLの構文解析段階になります。
t_userユーザ名= 'アリスから選択*;
このような従来のプリコンパイルされたSQLステートメントが既に変数が含まれていない、$ {}従って置換変数動的SQL構文解析ステージの段階ことがわかります。
3、#{}、{} $二つの方法の比較
1)SQLインジェクションを防ぐためです
前}#{SQLインジェクションを防止することができる; $ {}後、またはそれ以上の異なるアプローチが、見ることができ、注入されたプリコンパイルされ、リスク、次の例の前に置換されています。
入ってくるユーザー名は、SQLに解決するために処理した後「または」1 = 1、その後、直接置換文字列$は{}の場合:
t_userから選択*どこ名= A」または '1 = 1';
この場合、すべてのユーザーデータがチェックアウトされるので、SQLインジェクションに属します。
#{}場合は、動的な解像度とプリコンパイルされたSQLの後に、単一引用符は、その後、最終的に解決される\「SQLとしてエスケープされます:
これは、任意のデータを見つけることができません//効果的にSQLインジェクションを防ぐため、;ユーザ名=「\ 『または\』 1 = 1」はどこt_userから選択*
いくつかのビジネスシナリオが頻繁にファジークエリを使用し、その処理のように、ある、次のアプローチをお勧めします。
#ユーザー名#のようなt_user.username
Javaコード:
(もし!StringUtil.isEmpty(this.username)){
table.setUsername( "%" + this.username + "%")。
}
それとも、データベース接続処理機能を使用することがあります:
t_userから選択* U CONCATのようなユーザー名( '%'、#ユーザー名#、 '%')
注:上記のようなので、同じ定数を交換する必要のソートフィールド、テーブル名、カラム名、順として、特定のシナリオができるだけ$ {}、に見出すことができます。#{}場合は、次のようにテーブル名が、次のようになります。
#{テーブル名} SELECT * FROM - >テーブル名のパラメータ渡しをt_user --->「t_user」からの選択に後処理*、そのようなテーブルであり、誤差は、そう同じトークンによって順序であろう。
2)パフォーマンスの考慮事項
プリコンパイルされた文オブジェクトをプリコンパイルされ、キャッシュされた後、SQL PreparedStatementオブジェクトを生成するために再利用できるので、同じSQLの次は、直接キャッシュされたPreparedStatementオブジェクトを使用することができ、すべてのSQL用にコンパイル済みのデフォルトを、MyBatisの、この場合、#{}は処理性能が相対的に高いです。
要約:
{#}が} {#を使用することが可能な場合に使用でき
$ {}を使用して変数としてソートフィールドによってテーブル、オーダー。