MyBatis動的SQLステートメント
一般的に、mybatisの動的SQLステートメントには主に次のカテゴリがあります。
- ifステートメント(単純な条件付き判断)
- Java言語でのswitchと同等のchoose(when、otherwize)は、jstlでのchooseと非常によく似ています。
- トリム(含まれるコンテンツにプレフィックスまたはサフィックスなど、プレフィックス、サフィックスを追加する)
- where(主に、SQLステートメントのwhere条件の判断を単純化するために使用され、処理でき、またはインテリジェントに、冗長で文法エラーが発生することを心配しないでください)
- セット(主に更新時に使用)
- foreach(特にステートメントクエリでmybatisを実装する場合に役立ちます)
もし
動的SQLが通常行うことは、where句の一部を条件付きで含めることです。といった:
<select id="findActiveBlogWithTitleLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
</select>
このステートメントは、オプションのテキスト検索タイプ関数を提供します。「title」が渡されない場合、「ACTIVE」状態のすべてのBLOGが返されます。それ以外の場合、「title」が渡されると、「title」コンテンツのあいまい検索のBLOG結果が返されます。
選択する、いつ、そうでない場合
すべての条件ステートメントを使用するのではなく、1つまたは2つを選択したい場合があります。この状況に対応して、MyBatisはchoose要素を提供します。これは、Javaのswitchステートメントに少し似ています。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
トリム、場所、セット
前の例では、悪名高い動的SQLの問題を適切に解決しました。ここで、「if」の例に戻ることを検討します。今回は、動的条件として「ACTIVE = 1」を設定して、何が起こるかを確認します。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>
これらの条件のいずれも一致しない場合はどうなりますか?最終的に、このSQLは次のようになります。
SELECT * FROM BLOG
WHERE
これにより、クエリが失敗します。2番目の条件のみが一致する場合はどうなりますか?このSQLは次のようになります。
SELECT * FROM BLOG
WHERE
AND title like ‘yiibai.com’
MyBatisのプロセスは単純で、90%の場合に役立ちます。また、使用できない場所では、処理方法をカスタマイズして正しく動作させることができます。簡単な変更で目的の効果を得ることができます。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
where要素は、複数のif条件に値がある場合にのみ、「WHERE」句を挿入することを認識しています。さらに、最終的なコンテンツが「AND」または「OR」で始まる場合、where要素はそれらを削除する方法も知っています。
where要素が通常のパターンに従わない場合でも、trim要素をカスタマイズすることで必要な関数をカスタマイズできます。たとえば、where要素と同等のカスタムトリム要素は次のとおりです。
<trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>
prefixOverrides属性は、パイプで区切られたテキストシーケンスを無視します(この例のスペースも必要であることに注意してください)。その結果、prefixOverrides属性で指定されたすべてのコンテンツが削除され、prefix属性で指定されたコンテンツが挿入されます。動的更新ステートメントの同様のソリューションは、setと呼ばれます。set要素を使用すると、更新が必要な列を動的に含め、他の列は除外できます。といった:
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
ここで、set要素はSETキーワードの前に動的に配置され、余分なコンマも削除されます。これは、条件ステートメントが使用された後、これらのコンマが生成された割り当てステートメントの後ろに残る可能性があるためです。
同等のカスタムトリム要素がどのように見えるかに興味がある場合は、これがその正体である必要があります。
<trim prefix="SET" suffixOverrides=","> ... </trim>
foreach
動的SQLのもう1つの一般的で必要な操作は、通常IN条件ステートメントを作成するときにコレクションをトラバースする必要があることです。といった:
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
foreach要素の機能は非常に強力であり、コレクションを指定したり、コレクションアイテムを宣言したり、要素本体で使用できるインデックス変数を指定したりできます。また、一致を開始および終了するための文字列を指定し、反復の途中に区切り文字を配置することもできます。この要素は非常にスマートなので、誤って余分な区切り文字を追加することはありません。Listインスタンスまたは配列をパラメーターオブジェクトとしてMyBatisに渡すことができることに注意してください。これを行うと、MyBatisは自動的にそれをマップにラップし、名前をキーとして使用します。リストインスタンスはキーとして「list」を持ち、配列インスタンスはキーとして「array」を持ちます。