はじめに
サービス開発を行う中で、複数の条件で絞り込みを行なった結果をデータとして取得し一覧表示したい場面に遭遇した。そこで、複数条件を含めたリストを作成し、その要素をループで一つずつ取り出し、条件文に適用させる方法がないかと思い、調査を始めた。
実現したいこと
DBからデータを取得するときに、リストに含めた全要素を条件に付加したい。
調査
公式ドキュメントを参照したところ、MybatisのforEachタグを用いることで実現できそう。
foreach
動的 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>
実装
@Mapper
public interface MainListMapper {
public List<ACCOUNT> getMainUpperList(List<Integer> hideList);
}
<select id="getMainUpperList" resultType="com.example.matching.entity.ACCOUNT">
SELECT *
FROM ACCOUNT
WHERE ID NOT IN
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
ORDER BY CREATED DESC
</select>
躓いたところ
引数が一つの時は「collection="list"」の「list」の箇所に任意の名前が使用できたが、引数が二つ以上になった場合はinterfaceの引数で「@Param("hideList")」のように明示的に名前をつけてあげないと「collection="hideList"」をMybatis側で識別できない様子。
@Mapper
public interface MainListMapper {
public List<ACCOUNT> getMainLowerListMatchResidence(@Param("hideList") List<Integer> hideList, @Param("loginUserId") int loginUserId);
}
<select id="getMainLowerListMatchResidence" resultType="com.example.matching.entity.ACCOUNT">
SELECT *
FROM ACCOUNT
WHERE ID NOT IN
<foreach item="item" index="index" collection="hideList"
open="(" separator="," close=")">
#{item}
</foreach>
AND
RESIDENCE = (SELECT RESIDENCE FROM ACCOUNT WHERE ID = #{loginUserId})
ORDER BY CREATED DESC
</select>
まとめ
引数の数による影響で躓いたが、無事にリストの要素で条件を絞り込むことができた。
参考記事