6

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>

魅力のように機能します。

4

3 に答える 3

3

Actually, you can use the country value to look it up in the filter map and make it work as you initially had it. In the second loop, your collection will be defined as filter.get(country) and that should be good. This is of course considering I'm interpreting your question correctly.

于 2012-10-11T12:32:51.743 に答える
1

各マップキーがリストにマップされるマップとして何かを挿入する必要がありました。このようにクエリを書きました。

INSERT INTO TB_TEST (group_id, student_id) VALUES
<foreach collection="idMap.entrySet()" item="element" index="index" separator=",">
         <foreach collection="element.value" item="item" separator="," > 
            ( #{element.key}  #{item} )     
         </foreach> 
    </foreach>
于 2015-03-27T12:54:22.740 に答える