1. ホーム
  2. データベース
  3. エムエスエル

mybatis動的SQLの共通シナリオのまとめ

2022-01-18 11:22:43

前書き

通常、開発では、動的なSQLのためにこの作品は現在、弱点であり、ブログをテストしながら、対応するプロジェクトの公式サイトによると、自分の、これはちょうど動的なSQLの習熟度を深めることであり、より少ないがある 修正をご批判ください! このブログは、動的なSQLのためのものです。

1.もし

動的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" に向けて。
もし、"title"パラメータが渡されると、"title"カラムのファジー検索が行われ、対応するBLOG結果が返されます(注意深い読者は、"title"パラメータに検索マスクまたはワイルドカード文字が必要だと気付くかもしれません)。
quot;title"とquot;author"パラメーターによる任意検索を行いたい場合はどうすればよいでしょうか。まず、ステートメントの名前をもっと現実的なものに変えたいと思います。次に、別の条件を追加するだけです。

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = 'ACTIVE'
  <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>

2.選ぶ、時、それ以外

時には、すべての条件を使うのではなく、たくさんある条件のうちの一つだけを使いたいこともあります。このような場合のために、MyBatisでは、Javaのswitch文のようなchoose要素を用意しています。
上と同じ例ですが、"title"を渡すと"title"で探し、"author"を渡すと"author"で探す戦略に変更されています。どちらも渡されない場合は
は、featuredとマークされたBLOGを返します(これはおそらく、意味のないランダムなブログをたくさん返すよりも、管理者が選んだいくつかのブログを返す方がいいと考えたからでしょう)。

<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>

3.トリム、ホワイ、セット

これまでの例で、悪名高い動的SQLの問題の1つを都合よく解決することができました。今度は、前の"if"の例に戻って、"state = 'ACTIVE'"を動的条件に設定して、何が起こるか見てみましょう。

<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 'someTitle'

このクエリも失敗します。この問題は、条件付き要素を使うだけでは解決できません。この問題は、解決した人が二度と遭遇したくないと思うほど難解なものです。
MyBatisは、シンプルでほとんどのシナリオに適したソリューションを持っています。そして、他のシナリオでは、要件に合わせてカスタマイズすることができます。そして、これは、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>
  </where>
</select>

where要素は、子要素が何かを返す場合にのみ"WHERE"節を挿入します。また、節が "AND" または "OR" で始まっている場合、where 要素はそれらも削除します。
where要素が期待したものと異なる場合、trim要素をカスタマイズすることでwhere要素の機能をカスタマイズすることもできます。例えば、where 要素と同等の機能を持つカスタム trim 要素は次のようになります。

<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 キーワードが動的に挿入され、余分なカンマ(条件文を使って列に値を割り当てる場合に発生する)が削除されます。
set要素に相当するcustom trim要素を見てみましょう。

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

サフィックス値の設定を上書きし、プレフィックス値をカスタマイズしていることに注意してください。

4. フォアグラウンド

動的SQLのもう一つの一般的な使用シナリオは、コレクションをトラバースすることです(特に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要素は、コレクションの指定、コレクションアイテムの宣言、要素内で使用できるインデックス変数など、非常に強力な機能を持っています。また、コレクション項目の反復の間の開始文字列と終了文字列、セパレータを指定することができます。
この要素はまた、誤って余分なセパレータを追加することはありません。
ヒント foreachのコレクションパラメータとして、任意の反復可能オブジェクト(リスト、セットなど)、マップオブジェクト、配列オブジェクトを渡すことができます。反復可能オブジェクトや配列を使用する場合、indexは現在の反復処理の序数です。
itemの値は、このイテレーションで取り出した要素です。Map オブジェクト(または Map.Entry オブジェクトのコレクション)を使用する場合、index がキー、item が値となります。
ここまでで、XML設定ファイルとマッピングファイルについての解説は終了です。次の章では、作成したマッピング・コンフィギュレーションを活用できるように、Java APIを詳しく説明します。

mybatis動的SQLの概要についての記事は以上です。mybatis dynamic sqlの詳細については、スクリプト・ホームで過去の記事を検索するか、以下の関連記事を引き続きご覧ください。