有若干个参数,需要作为ibatis拼装sql的参数传入,但是有个参数的值比较特殊,是若干种枚举值。具体到这个case,就是有有限个namespace。我每次需要通过传入多个namespace来查询DB记录。
准备需要传入sqlmap的参数的示例代码如下:
- Map<String,Object> ibatisParam = new HashMap<String, Object>( );
-
- ibatisParam.put( "keyA","valueA" );
-
- List<String> list = new ArrayList<String>( );
- list.add( "namespace1" );
- list.add( "namespace2" );
-
- ibatisParam.put( "namespaces",list );
使用的ibatis的sql语句如下:
- <select id="listNodeByCriteria" parameterClass="java.util.Map" resultMap="NodeWithPropertyResult">
- select <include refid="NodeColumnsWithId"/> from node
- <dynamic prepend=" where ">
- <isNotNull property="namespaces">
- namespace in
- <iterate property="namespaces" open="(" conjunction="," close=")">
- #value[]#
- </iterate>
- </isNotNull>
- </dynamic>
- order by id
- limit #querySize# offset #startRow#
- </select>
这里的基本需求是map中如果有namespaces这个key,则他的value一定是个list,并且要以这个list作为查询数据的条件。
开始这么写的,报了如下诡异的错误:
这个错误提示真的好烂。被NumberFormatException搞迷糊了好一阵。
后来请教同事,把上面的sqlmap中的语句改成下面这样就Ok了:
- <select id="listNodeByCriteria" parameterClass="java.util.Map" resultMap="NodeWithPropertyResult">
- select <include refid="NodeColumnsWithId"/> from node
- <dynamic prepend=" where ">
- <isNotNull property="namespaces">
- namespace in
- <iterate property="namespaces" open="(" conjunction="," close=")">
- #namespaces[]#
- </iterate>
- </isNotNull>
- </dynamic>
- order by id
- limit #querySize# offset #startRow#
- </select>
注意,这里只有iterate标签内部的value改成了namespaces,其他完全一样。
原来在这种定位JavaBean(这里是map)内部的list属性的时候,iterate标签内部的变量名就要与标签上的property属性的值保持一致了。
问题原因:
参考上面的准备Map的Java代码,可以看到,namespaces作为Map的一个key,ibatis在解析的时候,也只能根据这个key来找到他需要遍历的list(就是我们put进去的那个跟namespaces对应的value)。所以这里不能使用namespaces以外的字符串来用在iterate标签内部,必须使用namespaces,这个是由Map在put时使用的key的名字决定的。只是上面的写法确实不太常见,看上去感觉有点像namespaces本身像个集合,这点是需要注意的。
问题升级:
上面问题中,Map里面namespaces对应的list里面的元素还是简单的String,所以在上面直接遍历里面的内容即可。但是如果这个list的内容不是String,而是一个对象,比如叫NameSpace,即List<String> --> List<NameSpace>,这里NameSpace的示例代码如下:
- class NameSpace{
- String name;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
- }
如果上面的sql中的namespace需要从NameSpace中的name属性取出,这种该怎么写呢?
这里只列出关键有区别的代码,其他地方省略。。。
- namespace in
- <iterate property="namespaces" open="(" conjunction="," close=")">
- #namespaces[].name#
- </iterate>
这里,回想一下上面列出的简单场景的情况,这种写法也不难理解。
参考:http://hittyt.iteye.com/blog/1518665