Mybatisのwhere句でforeachを使用

Mybatisのwhere句でforeachを使用

MyBatisのwhere句では、リストや配列の要素でforeachを使うことで、SQL文に複数の条件を追加することができます。
whereでINを使う場合に頻繁に使用します。
以下がその具体的な実装方法とサンプルになります。

基本的な考え方

MyBatisのforeachをwhere句で使用する目的は、動的に複数の条件を追加することです。
例えば、ユーザーが複数の条件でデータを検索したい場合、これをforeachで効率的に処理できます。
ここでは、test_userテーブルからユーザー情報を検索する例を用います。

テーブルの構造

まず、test_userテーブルの構造についてです。
次のようなテーブルがあるとします。

CREATE TABLE test_user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    age INT,
    city VARCHAR(100)
);

このテーブルに対して、名前、年齢、都市のいずれかで検索を行うクエリを作成します。

MyBatisのマッパーXMLファイルの例

以下は、test_userテーブルに対して複数の検索条件を動的に生成するSQLクエリのマッパーXMLファイルの例です。

<mapper namespace="com.example.mapper.UserMapper">

    <!-- ユーザー検索クエリ -->
    <select id="selectUsers" parameterType="map" resultType="com.example.model.User">
        SELECT * FROM test_user
        WHERE 1=1
        <if test="nameList != null and nameList.size() > 0">
            AND name IN
            <foreach item="name" collection="nameList" open="(" separator="," close=")">
                #{name}
            </foreach>
        </if>
        <if test="ageList != null and ageList.size() > 0">
            AND age IN
            <foreach item="age" collection="ageList" open="(" separator="," close=")">
                #{age}
            </foreach>
        </if>
        <if test="cityList != null and cityList.size() > 0">
            AND city IN
            <foreach item="city" collection="cityList" open="(" separator="," close=")">
                #{city}
            </foreach>
        </if>
    </select>

</mapper>

上記のSQLクエリの説明

  • nameList, ageList, cityListは、クエリパラメータとして渡されるリストです。
  • ifタグを使って、リストがnullでなく、かつサイズが0より大きい場合に条件を追加します。
  • foreachタグを使って、リストの各要素をIN句に追加します。

open属性で開き括弧、separator属性でカンマ、close属性で閉じ括弧を設定します。

Javaのマッパーインターフェースの例

対応するJavaのマッパーインターフェースは以下のようになります。

public interface UserMapper {

    List<User> selectUsers(Map<String, Object> params);

}

使用方法

このクエリを使用するためには、クエリパラメータとして適切なリストを含むMapを作成します。
以下は、サービス層での使用例です。

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public List<User> searchUsers(List<String> names, List<Integer> ages, List<String> cities) {
        Map<String, Object> params = new HashMap<>();
        // それぞれListを渡している
        params.put("nameList", names);
        params.put("ageList", ages);
        params.put("cityList", cities);

        return userMapper.selectUsers(params);
    }

}

まとめ

この例では、test_userテーブルに対して、複数の検索条件を動的に組み合わせて検索する方法を示しました。
foreachタグを使用することで、リストの内容に基づいた柔軟なSQLクエリを生成できます。
ifタグと組み合わせることで、条件の有無に応じてSQLを構築できるため、非常に便利です。