原始需求:

有若干个参数,需要作为ibatis拼装sql的参数传入,但是有个参数的值比较特殊,是若干种枚举值。具体到这个case,就是有有限个namespace。我每次需要通过传入多个namespace来查询DB记录。

准备需要传入sqlmap的参数的示例代码如下:

  1. Map<String,Object> ibatisParam = new HashMap<String, Object>( );
  2. ibatisParam.put( "keyA","valueA" );
  3. List<String> list = new ArrayList<String>( );
  4. list.add( "namespace1" );
  5. list.add( "namespace2" );
  6. ibatisParam.put( "namespaces",list );

使用的ibatis的sql语句如下:

  1. <select id="listNodeByCriteria"  parameterClass="java.util.Map" resultMap="NodeWithPropertyResult">
  2. select <include refid="NodeColumnsWithId"/> from node
  3. <dynamic prepend=" where ">
  4. <isNotNull property="namespaces">
  5. namespace in
  6. <iterate property="namespaces" open="(" conjunction="," close=")">
  7. #value[]#
  8. </iterate>
  9. </isNotNull>
  10. </dynamic>
  11. order by id
  12. limit #querySize# offset #startRow#
  13. </select>

这里的基本需求是map中如果有namespaces这个key,则他的value一定是个list,并且要以这个list作为查询数据的条件。

开始这么写的,报了如下诡异的错误:

  1. java.lang.reflect.InvocationTargetException
  2. at java.lang.reflect.Method.invoke(Method.java:597)
  3. at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:76)
  4. at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.access$001(AbstractAnnotationAwareTransactionalTests.java:71)
  5. at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests$1.run(AbstractAnnotationAwareTransactionalTests.java:175)
  6. at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTest(AbstractAnnotationAwareTransactionalTests.java:283)
  7. at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTestTimed(AbstractAnnotationAwareTransactionalTests.java:254)
  8. at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runBare(AbstractAnnotationAwareTransactionalTests.java:172)
  9. at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
  10. at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
  11. at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
  12. at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
  13. at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
  14. at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
  15. Caused by: java.lang.reflect.InvocationTargetException
  16. at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
  17. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  18. at java.lang.reflect.Method.invoke(Method.java:597)
  19. at mockit.integration.junit3.internal.JUnitTestCaseDecorator.runTest(JUnitTestCaseDecorator.java:146)
  20. at junit.framework.TestCase.runTest(TestCase.java)
  21. at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
  22. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  23. at java.lang.reflect.Method.invoke(Method.java:597)
  24. at mockit.integration.junit3.internal.JUnitTestCaseDecorator.runTest(JUnitTestCaseDecorator.java:146)
  25. at mockit.integration.junit3.internal.JUnitTestCaseDecorator.originalRunBare(JUnitTestCaseDecorator.java:105)
  26. at mockit.integration.junit3.internal.JUnitTestCaseDecorator.runBare(JUnitTestCaseDecorator.java:90)
  27. at junit.framework.TestCase.runBare(TestCase.java)
  28. at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:76)
  29. at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.access$001(AbstractAnnotationAwareTransactionalTests.java:71)
  30. at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests$1.run(AbstractAnnotationAwareTransactionalTests.java:175)
  31. at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTest(AbstractAnnotationAwareTransactionalTests.java:283)
  32. at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTestTimed(AbstractAnnotationAwareTransactionalTests.java:254)
  33. at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runBare(AbstractAnnotationAwareTransactionalTests.java:172)
  34. at junit.framework.TestResult$1.protect(TestResult.java:110)
  35. at junit.framework.TestResult.runProtected(TestResult.java:128)
  36. at junit.framework.TestResult.run(TestResult.java:113)
  37. at junit.framework.TestCase.run(TestCase.java:124)
  38. at junit.framework.TestSuite.runTest(TestSuite.java:232)
  39. at junit.framework.TestSuite.run(TestSuite.java:227)
  40. at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:81)
  41. ... 6 more
  42. Caused by: org.springframework.jdbc.UncategorizedSQLException: SqlMapClient operation; uncategorized SQLException for SQL []; SQL state [null]; error code [0];
  43. --- The error occurred in META-INF/ibatis/mysql/Node.xml.
  44. --- The error occurred while preparing the mapped statement for execution.
  45. --- Check the Node.listNodeByCriteria.
  46. --- Check the parameter map.
  47. --- Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list from JavaBean. Cause java.lang.NumberFormatException: For input string: ""; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
  48. --- The error occurred in META-INF/ibatis/mysql/Node.xml.
  49. --- The error occurred while preparing the mapped statement for execution.
  50. --- Check the Node.listNodeByCriteria.
  51. --- Check the parameter map.
  52. --- Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list from JavaBean. Cause java.lang.NumberFormatException: For input string: ""
  53. at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)
  54. at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
  55. at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
  56. at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:212)
  57. at org.springframework.orm.ibatis.SqlMapClientTemplate.executeWithListResult(SqlMapClientTemplate.java:249)
  58. at org.springframework.orm.ibatis.SqlMapClientTemplate.queryForList(SqlMapClientTemplate.java:296)
  59. at com.alibaba.genova.dependency.common.dao.impl.NodeDaoImpl.listNodesByCriteria(NodeDaoImpl.java:116)
  60. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  61. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  62. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  63. at java.lang.reflect.Method.invoke(Method.java:597)
  64. at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
  65. at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
  66. at $Proxy8.listNodesByCriteria(Unknown Source)
  67. at com.alibaba.genova.dependency.common.dao.NodeDAOTest.testListNodeByCriteriaWithNameSpace(NodeDAOTest.java:295)
  68. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  69. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  70. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  71. at java.lang.reflect.Method.invoke(Method.java:597)
  72. at junit.framework.TestCase.runTest(TestCase.java:168)
  73. ... 31 more
  74. Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:
  75. --- The error occurred in META-INF/ibatis/mysql/Node.xml.
  76. --- The error occurred while preparing the mapped statement for execution.
  77. --- Check the Node.listNodeByCriteria.
  78. --- Check the parameter map.
  79. --- Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list from JavaBean. Cause java.lang.NumberFormatException: For input string: ""
  80. at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:204)
  81. at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryForList(MappedStatement.java:139)
  82. at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:567)
  83. at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:541)
  84. at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessionImpl.java:118)
  85. at org.springframework.orm.ibatis.SqlMapClientTemplate$3.doInSqlMapClient(SqlMapClientTemplate.java:298)
  86. at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:209)
  87. ... 47 more
  88. Caused by: com.ibatis.common.beans.ProbeException: Error getting ordinal list from JavaBean. Cause java.lang.NumberFormatException: For input string: ""
  89. at com.ibatis.common.beans.BaseProbe.getIndexedProperty(BaseProbe.java:86)
  90. at com.ibatis.common.beans.ComplexBeanProbe.getProperty(ComplexBeanProbe.java:297)
  91. at com.ibatis.common.beans.ComplexBeanProbe.getObject(ComplexBeanProbe.java:198)
  92. at com.ibatis.common.beans.GenericProbe.getObject(GenericProbe.java:74)
  93. at com.ibatis.sqlmap.engine.exchange.ComplexDataExchange.getData(ComplexDataExchange.java:65)
  94. at com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap.getParameterObjectValues(ParameterMap.java:133)
  95. at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:181)
  96. ... 53 more
  97. Caused by: java.lang.NumberFormatException: For input string: ""
  98. at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
  99. at java.lang.Integer.parseInt(Integer.java:470)
  100. at java.lang.Integer.parseInt(Integer.java:499)
  101. at com.ibatis.common.beans.BaseProbe.getIndexedProperty(BaseProbe.java:51)
  102. ... 59 more

这个错误提示真的好烂。被NumberFormatException搞迷糊了好一阵。

后来请教同事,把上面的sqlmap中的语句改成下面这样就Ok了:

  1. <select id="listNodeByCriteria"  parameterClass="java.util.Map" resultMap="NodeWithPropertyResult">
  2. select <include refid="NodeColumnsWithId"/> from node
  3. <dynamic prepend=" where ">
  4. <isNotNull property="namespaces">
  5. namespace in
  6. <iterate property="namespaces" open="(" conjunction="," close=")">
  7. #namespaces[]#
  8. </iterate>
  9. </isNotNull>
  10. </dynamic>
  11. order by id
  12. limit #querySize# offset #startRow#
  13. </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的示例代码如下:

  1. class NameSpace{
  2. String name;
  3. public String getName() {
  4. return name;
  5. }
  6. public void setName(String name) {
  7. this.name = name;
  8. }
  9. }

如果上面的sql中的namespace需要从NameSpace中的name属性取出,这种该怎么写呢?

这里只列出关键有区别的代码,其他地方省略。。。

  1. <!--namespace是DB中的字段名-->
  2. namespace in
  3. <!--namespaces是Java代码中Map里面List对应的Key-->
  4. <iterate property="namespaces" open="(" conjunction="," close=")">
  5. <!--每一个NameSpace实例的name属性通过namespaces[].name获取-->
  6. #namespaces[].name#
  7. </iterate>

这里,回想一下上面列出的简单场景的情况,这种写法也不难理解。

参考:http://hittyt.iteye.com/blog/1518665

Ibatis中sqlmap参数map中还需要套list的情况如何写?的更多相关文章

  1. ArcGIS Engine中如何获取Map中已经选择的要素呢(转)

    ArcGIS Engine中如何获取Map中已经选择的要素呢   1.使用IEnumFeturea对象获取map中的FeatureSelection,该方法可以获取所有图层的选择要素.IMap中的Fe ...

  2. Java:TreeMap中LinkedHashMap和Map中HashMap的区别

    一般情况下,我们用的最多的是HashMap,在Map 中插入.删除和定位元素,HashMap 是最好的选择. 但如果您要bai按自然顺序或自定义顺序遍历键,那么TreeMap会更好.如果需要输出的顺序 ...

  3. ArcGIS Engine中如何获取Map中已经选择的要素呢

    1.使用IEnumFeturea对象获取map中的FeatureSelection,该方法可以获取所有图层的选择要素.IMap中的FeatureSelection可不是IFeatureSelectio ...

  4. MyBatis动态SQL使用,传入参数Map中的Key判断

    <select id="" parameterType="Map" resultMap="commodityResultMap" &g ...

  5. js获取url中的参数,url中传递中文的时候通过js解码的方式

    如果传递的参数是: <a href="${pageContext.request.contextPath}/productdisplay/productDisplay_productD ...

  6. 如何在模板中引用参数类中的一个特定member

    C++模板有很多特性需要我们去挖掘,很多新的设计模式也都与模板使用相关,我们知道模板的一个基本特性就是可以根据传入的类型产生新的类型.围绕这个特性,可以衍生出很多的其它特性,比如自动为不同的类生成st ...

  7. C++中如何按照map中的value来进行排序

    sort函数无法对map进行排序,网上的方法一般是通过将map转为vector后,再来使用sort进行排序. 如下, 比较函数 bool cmp(const pair<int,int> & ...

  8. java获取request中的参数、java解析URL问号后的参数

    java获取request中的参数.java解析URL问号后的参数.有时候我们需要从request中获取参数,或者获取拼接在Url后面的参数,有时候一个一个去拿有点麻烦,一起拿出来放在一个map里面需 ...

  9. mybatis从dao传入多个参数到sqlmap时dao中要使用map或实例对象(如:user)作为参数传入, 否则报错找不到属性getter方法

    23:37 2015-07-02 注意1. 使用mybaits的resultMap查询时, 如果想传入多个参数(比如where 1=1动态多条件查询时)sqlmap文件中对应的方法中, selectL ...

随机推荐

  1. bzoj3998 [TJOI2015]弦论(SAM)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3998 [题意] 询问排名第k的子串是谁,0代表相同子串不同位置算作相同,1代表相同子串 ...

  2. 【Java基础】基本类型的包装类作为参数传递是值传递还是引用传递

    突然想到这个问题,然后做了下实验,下面以Integer来讲解,其他的忽略: import java.util.Iterator; /** * Created by lili on 15/9/24. * ...

  3. poj 2942--Knights of the Round Table (点的双连通分量)

    做这题简直是一种折磨... 有n个骑士,骑士之间相互憎恨.给出骑士的相互憎恨的关系. 骑士要去开会,围成一圈坐,相互憎恨的骑士不能相邻.开会骑士的个数不能小于三个人.求有多少个骑士不能开会. 注意:会 ...

  4. poj 3281 Dining【拆点网络流】

    Dining Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11828   Accepted: 5437 Descripti ...

  5. 算法基础:最大递减数问题(Golang实现)

    给出一个非负整数,找到这个非负整数中包括的最大递减数.一个数字的递减数是指相邻的数位从大到小排列的数字. 如: 95345323,递减数有:953,95,53,53,532,32, 那么最大的递减数为 ...

  6. android webview内容压线问题解决方法

    最近在使用webview做页面开发,项目上要求webview在获取到焦点的时候需要有边框线,于是添加上了webview的选中效果,但是出现了网页中的内容压选中框的情况.之后给webview添加padd ...

  7. My安装Eclipse三种方法插件

    Eclipse它是一个开源项目,但非常需要手动集成插件,MyEclipse在Eclipse插件.但非常多时候MyEclipse相同须要再次安装插件,插件安装有三种方法,以下以SVN为例.具体阐述. E ...

  8. MySQL主主复制+LVS+Keepalived实现MySQL高可用性

    http://bestvivi.com/2015/09/09/MySQL%E4%B8%BB%E4%B8%BB%E5%A4%8D%E5%88%B6+LVS+Keepalived%E5%AE%9E%E7% ...

  9. careercup-树与图 4.9

    4.9 给定一颗二叉树,其中每个结点都含有一个数值.设计一个算法,打印结点数值总和等于某个给定值的所有路径.注意,路径不一定非得从二叉树的根节点或叶子节点开始或结束. 类似于leetcode:Path ...

  10. 整理 iOS 9 适配中出现的坑

    本文主要是说一些iOS9适配中出现的坑,如果只是要单纯的了解iOS9新特性可以看瞄神的开发者所需要知道的 iOS 9 SDK 新特性.9月17日凌晨,苹果给用户推送了iOS9正式版,随着有用户陆续升级 ...