MyBatis 3.0.6 を使用して、次の問題の解決策を見つけようとしています。
一連のパラメーターに基づいて動的な select ステートメントを作成する必要があります。そのうちの 1 つは typeHashMap<String, List<String>>
です。課題は、MyBatis が外側のforeachループですべてのキーを反復処理する方法と、内側のループで値リストの要素を反復処理する方法を理解することです。
説明のために、フィルターと呼ばれる私のハッシュ マップ パラメーターに、次のように国 (キーとしての国コード) ごとに州 (州コードのリスト、各リストが値である) が含まれているとします。
'US' -> {'CO','NY','MI','AZ'};
'CA' -> {'ON','BC','QC'}
動的 SQL を次のようにする必要があります (非常に簡略化された形式で)。
SELECT *
FROM Table1
WHERE ... some static criteria goes here...
AND RowId IN (SELECT RowId FROM Table2 WHERE Country = 'US' AND State IN ('CO','NY','MI','AZ')
AND RowId IN (SELECT RowId FROM Table2 WHERE Country = 'CA' AND State IN ('ON','BC,'QC')
私のマッパー XML は次のようになると思います。
<select id="getData" resultType="QueryResult">
SELECT *
FROM Table1
WHERE ... some static criteria goes here...
<if test="filter != null">
<foreach item="country" index="i" collection="filter" separator="AND">
RowId IN (SELECT RowId
FROM Table2
WHERE Country = #{country} AND State IN
<foreach item="state" index="j" collection="country.states" separator="," open="(" close=")">
#{state}
</foreach>
</foreach>
</if>
</select>
問題は、 country.statesをネストされたforeachループで反復処理するための適切な構文は何かということです。
アップデート
いろいろいじくり回した後、MyBatis を HashMap ベースのアプローチでうまく動作させることができなかったので、複数の値を親の値にマップする新しいクラスを追加し、そのようなオブジェクトのリストを MyBatis に渡しました。上記の国/州の例を使用すると、クラスは次のようになります。
public class Filter {
private String country;
private ArrayList<String> states;
// ... public get accessors here ...
}
DAO メソッド:
public void QueryResult[] getResults( @Param("criteria") List<Filter> criteria) ...
そして MyBatis マッピング:
<select id="getData" resultType="QueryResult">
SELECT *
FROM Table1
WHERE ... some static criteria goes here...
<if test="criteria!= null">
<foreach item="filter" index="i" collection="criteria" separator="AND" open="AND">
RowId IN (SELECT RowId
FROM Table2
WHERE Country = #{filter.country} AND State IN
<foreach item="state" index="j" collection="filter.states" separator="," open="(" close=")">
#{state}
</foreach>
</foreach>
</if>
</select>
魅力のように機能します。