2012-09-10 45 views
5

我试图找出一个解决方案使用的MyBatis 3.0.6以下问题:嵌套的foreach一个HashMap的参数

我需要根据一系列参数来构建一个动态的select语句,一个其中类型为HashMap<String, List<String>>。我们面临的挑战是如何让MyBatis迭代外部循环中的所有键,以及迭代内部循环中值列表的元素。

为了说明,假设我的哈希表的参数调用过滤包含状态(的状态代码列表,每个列表作为值),每个国家(国家代码为重点),像这样:

'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循环遍历?


UPDATE

一些修修补补之后,我无法得到的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> 

就像一个魅力。

回答

3

实际上,您可以使用国家/地区值在过滤器映射中查找并使其按照您最初的状态工作。在第二个循环中,您的集合将被定义为filter.get(country),这应该是好的。这当然是考虑到我正确地解释你的问题。

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

这个!为我修好了。谢谢! – 98percentmonkey

0

截至目前,我可以做到这一点。

<foreach collection="myMap" index="key" item="value"> 
    <foreach collection="value" item="element"> 
    ... = #{key} ... 
    ... = #{element}) 
    </foreach> 
</foreach>