Java

MyBatisでLIKE句(部分一致、前方一致、後方一致)を実装する

2022年7月20日

MyBatisでLIKE検索

CONCAT関数を使用する

MyBatisで「部分一致」「前方一致」「後方一致」検索する場合は、LIKEとCONCAT関数を使って記述します。

■部分一致

LIKE CONCAT('%', #{value}, '%')

■前方一致

LIKE CONCAT(#{value}, '%')

■後方一致

LIKE CONCAT('%', #{value})

下記はMyBatisでLIKE句を使ったSELECT文の例です。

<select id="search" resultType="com.example.demo.entity.UserInfo">
    SELECT
        *
    FROM
        userinfo
    WHERE
        delete_date IS NULL
        <if test="id != null and id != ''">
            AND id = #{id}
        </if>
        <if test="name != null and name != ''">
            AND name LIKE CONCAT('%', #{name}, '%')
        </if>
</select>

スポンサーリンク

LIKE句を使用する際はSQLインジェクションに要注意

MyBatisでは、部分一致を次のように記述することもできます。

LIKE '%${value}%'

一見問題なさそうに見えるのですが、この書き方は「SQLインジェクション」が発生します。

<select id="search" resultType="com.example.demo.entity.UserInfo">
    SELECT
        *
    FROM
        userinfo
    WHERE
        name LIKE '%${name}%'
</select>

例えば、上記のようなLIKE句を使ったSQLに対してパラメータ「name」にシングルクォーテーションを入力すると「SELECT * FROM userinfo WHERE name LIKE '%'%'」というSQL文を生成します。そしてこのSQL文を実行するとエラーが発生します。

これは外部からのパラメータによってSQL文が操作されたため発生した現象です。

このように外部からのパラメータにより想定しないSQL文を生成しデータベースを不正操作するサイバー攻撃のことをSQLインジェクションといいます。

今回の例では、外部からのパラメータがシングルクォーテーションだけだったので、SQL文がエラーになるだけで済みましたが、SQLインジェクション攻撃では巧なSQL文を作りデータベースを不正操作します。

MyBatisで${}を利用するときは注意が必要です。

${value}はvalueの値をそのまま出力します。そのため、画面から利用者が入力した値や他システムから連携してきた値に対して${}を使用するべきではありません。SQLインジェクションが発生します。

もし使用する場合は、外部からの値をエスケープしてから使用するか、外部から不正な値が入ってこないこと確認したう上で使用する必要があります。

#{value}の場合は、シングルクォーテーションなどSQL文を構成する要素に対して、エスケープを実施してくれます。そして文字列の場合はシングルクォーテーションで囲ってくれます。そのため、#{}を使っていればSQLインジェクションが発生することはありません。

「LIKE '%${value}%'」の書き方は、意外に書いてしまいがちなので要注意です。

helpful