MyBatisの動的SQLについて

こんにちわ。
NOBORIの村越です。

今回は、最近勉強し始めたMyBatisの動的SQLについて書こうと思います。

MyBatisとは何か

XMLを使って、SQL文とオブジェクトをマッピングするフレームワークです。
パラメータを渡し、動的にSQLを発行することが出来ます。
詳しくはこちらを参照ください。

if

<select id="select">
  select
    *
  from
    sample_table 
  where
    name = #{name, jdbcType=VARCHAR}
    <if test="age != null">
      and age = #{age, jdbcType=VARCHAR}
    </if>
</select>

条件を満たす場合、特定の処理を行いたい場合は、if文を使用します。
パラメータの age が存在する場合は、name と age を、
存在しない場合は name のみを条件として取得するSQLとなります。

choose

<select id="select">
  select
    *
  from
    sample_table
  where
    <choose>
      <when test="number != null">
        number = #{number, jdbcType=VARCHAR}
      </when>
      <when test="name != null">
        name = #{name, jdbcType=VARCHAR}
      </when>
      <otherwise>
        age = #{age, jdbcType=VARCHAR}
      </otherwise>
    </choose>
</select>

条件のうち、どれか一つの処理のみを行いたい場合、choose文を使用します。
パラメータの number が存在する場合は number を、
number が存在せず、name が存在する場合は name を、
どちらも存在しない場合は age を条件として取得するSQLとなります。

where

上で紹介した if 文を使用して、以下のようなパラメータ number、name、age のうち存在するもの全てを条件として取得を行うSQLを書いたとします

<select id="select">
  select
    *
  from
    sample_table
  where
    <if test="number != null">
      number = #{number, jdbcType=VARCHAR}
    </if>
    <if test="name != null">
      and name = #{name, jdbcType=VARCHAR}
    </if>
    <if test="age != null">
      and age = #{age, jdbcType=VARCHAR}
    </if>
</select>

上記の例の場合、すべての条件が存在しない場合、
select * from sample_table where
というSQLになり、構文エラーとなってしまいます。

また、number が存在せず、name が存在する場合、
select * from sample_table where and name = #{name, jdbcType=VARCHAR}
というSQLになり、こちらも構文エラーになります。

上記のような場合には、where文を使用するといいです。

<select id="select">
  select
    *
  from
    sample_table
  <where>
    <if test="number != null">
      number = #{number, jdbcType=VARCHAR}
    </if>
    <if test="name != null">
      and name = #{name, jdbcType=VARCHAR}
    </if>
    <if test="age != null">
      and age = #{age, jdbcType=VARCHAR}
    </if>
  </where>
</select>

条件のうち、どれか一つでも満たした場合は、whereを挿入し、
where句の最初が and、or で始まってしまうSQL文になる場合は、不要な and、or を削除してくれます。
例えば、name と age が存在する場合は
select * from sample_table where name = #{name, jdbcType=VARCHAR} and age = #{age, jdbcType=VARCHAR}
といったSQLになります。

set

<update id="update">
  update
    sample_table 
  <set>
    <if test="name != null">
      name = #{name, jdbcType=VARCHAR},
    </if>
    <if test="age != null">
      age = #{age, jdbcType=VARCHAR}
    </if>
  </set>
  where
    number = #{number, jdbcType=VARCHAR}
</update>

where文の set 版になります。
条件を一つでも満たす場合は set を挿入し、set句の最後が , で終わる場合は , を削除してくれます。

trim

<select id="select">
  select
    *
  from
    sample_table
  <trim prefix="WHERE" prefixOverrides="AND |OR ">
    <if test="number != null">
      number = #{number, jdbcType=VARCHAR}
    </if>
    <if test="name != null">
      and name = #{name, jdbcType=VARCHAR}
    </if>
    <if test="age != null">
      and age = #{age, jdbcType=VARCHAR}
    </if>
  </trim>
</select>

上記の where、set を自分で定義することができるのが trim文です。
上記の where の例を trimで書き換えたものになります。
prefix、suffix で、条件を一つでも満たした場合に先頭、末尾に付与する文字を、prefixOverrides、suffixOverrides で、先頭、末尾の削除する文字を指定できます。

foreach

<select id="select">
  select
    *
  from
    sample_table
  where
    number in
      <foreach item="item" collection="numberList" open="(" separator="," close=")">
        #{item, jdbcType=VARCHAR}
      </foreach>
</select>

配列の要素を条件に指定したい場合は、foreach文を使用します。
collection で指定された配列の要素を separator で区切り、open、closeを最初と最後に付与します。
上記の例では、以下のようなSQLとなります。
select * from sample_table where number in (aaa, bbb, ccc)

include、sql

<sql id="selectAll">
  select
    *
  from
    sample_table
</sql>

<select id="selectName">
  <include refid="selectAll" />
  where
    name = #{name, jdbcType=VARCHAR}
</select>

<select id="selectNumber">
  <include refid="selectAll" />
  where
    number = #{number, jdbcType=VARCHAR}
</select>

sql で定義したSQLを、include で呼び出すことが出来ます。
上記の例では、selectName、selectNumberは、それぞれ name、number を指定して sample_table からデータを取得するSQLになります。
select * from sample_table の部分を include を使用して省略しています。
よく使用するSQLを定義しておけば、何度も同じSQLを書く必要がなくなります。

最後に

Mybatisの動的SQLについてまとめてみましたが、いかがだったでしょうか?

動的SQLはとても便利で、使えると記載がすごく楽になります。
今回紹介した動的SQL以外にもMybatisには便利な機能があるので、機会があればまとめてみようかと思います。

今回は以上となります。
今後とも「NOBORI」をよろしくお願い致します。

村越