Foreach imbriquée dans MyBatis 3 pour une HashMap paramètre

Je suis en train d'essayer de trouver une solution pour le problème suivant à l'aide de MyBatis 3.0.6:

J'ai besoin de construire une dynamique de sélectionner déclaration fondée sur une série de paramètres, dont l'un est de type HashMap<String, List<String>>. Le défi est de comprendre comment faire de MyBatis itérer sur toutes les touches à l'extérieur de foreach boucle ainsi que d'itérer sur les éléments de la liste de valeur dans la boucle interne.

Pour illustrer, supposons que mon hash map paramètre appelé filtre contient les états (liste des codes d'état, chaque liste étant la valeur) par pays (country code de la clé), comme suit:

'US' -> {'CO','NY','MI','AZ'};
'CA' -> {'ON','BC','QC'}

J'ai besoin de mon code SQL dynamique pour ressembler à ceci (dans une grave forme simplifiée):

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')

J'imagine mon mappeur XML devrait ressembler à quelque chose comme ceci:

<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>

La question est donc, quelle est la bonne syntaxe pour obtenir le pays.les états à parcourir dans le imbriqués foreach boucle?


Mise à JOUR

Après quelques retouches, je ne pouvais pas obtenir MyBatis à jouer très bien avec la table de hachage basée sur l'approche, j'ai donc fini par l'ajout d'une nouvelle classe qui associe plusieurs valeurs à leur valeur parent, puis en passant une liste de ces objets MyBatis. À l'aide de l'un des pays/états de l'exemple ci-dessus, la classe ressemble à ceci:

public class Filter {
   private String country;
   private ArrayList<String> states;

   //... public get accessors here ...
}

La méthode DAO:

public void QueryResult[] getResults( @Param("criteria") List<Filter> criteria) ...

Et la MyBatis cartographie:

<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>

Fonctionne comme un charme.

OriginalL'auteur Caspian Canuck | 2012-09-10