Ibatis中sqlmap参数map中还需要套list的情况如何写?
原始需求:
有若干个参数,需要作为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作为查询数据的条件。
开始这么写的,报了如下诡异的错误:
- java.lang.reflect.InvocationTargetException
- at java.lang.reflect.Method.invoke(Method.java:597)
- at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:76)
- at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.access$001(AbstractAnnotationAwareTransactionalTests.java:71)
- at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests$1.run(AbstractAnnotationAwareTransactionalTests.java:175)
- at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTest(AbstractAnnotationAwareTransactionalTests.java:283)
- at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTestTimed(AbstractAnnotationAwareTransactionalTests.java:254)
- at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runBare(AbstractAnnotationAwareTransactionalTests.java:172)
- at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
- at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
- at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
- at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
- at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
- at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
- Caused by: java.lang.reflect.InvocationTargetException
- at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at mockit.integration.junit3.internal.JUnitTestCaseDecorator.runTest(JUnitTestCaseDecorator.java:146)
- at junit.framework.TestCase.runTest(TestCase.java)
- at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at mockit.integration.junit3.internal.JUnitTestCaseDecorator.runTest(JUnitTestCaseDecorator.java:146)
- at mockit.integration.junit3.internal.JUnitTestCaseDecorator.originalRunBare(JUnitTestCaseDecorator.java:105)
- at mockit.integration.junit3.internal.JUnitTestCaseDecorator.runBare(JUnitTestCaseDecorator.java:90)
- at junit.framework.TestCase.runBare(TestCase.java)
- at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:76)
- at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.access$001(AbstractAnnotationAwareTransactionalTests.java:71)
- at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests$1.run(AbstractAnnotationAwareTransactionalTests.java:175)
- at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTest(AbstractAnnotationAwareTransactionalTests.java:283)
- at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTestTimed(AbstractAnnotationAwareTransactionalTests.java:254)
- at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runBare(AbstractAnnotationAwareTransactionalTests.java:172)
- at junit.framework.TestResult$1.protect(TestResult.java:110)
- at junit.framework.TestResult.runProtected(TestResult.java:128)
- at junit.framework.TestResult.run(TestResult.java:113)
- at junit.framework.TestCase.run(TestCase.java:124)
- at junit.framework.TestSuite.runTest(TestSuite.java:232)
- at junit.framework.TestSuite.run(TestSuite.java:227)
- at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:81)
- ... 6 more
- Caused by: org.springframework.jdbc.UncategorizedSQLException: SqlMapClient operation; uncategorized SQLException for SQL []; SQL state [null]; error code [0];
- --- The error occurred in META-INF/ibatis/mysql/Node.xml.
- --- The error occurred while preparing the mapped statement for execution.
- --- Check the Node.listNodeByCriteria.
- --- Check the parameter map.
- --- 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:
- --- The error occurred in META-INF/ibatis/mysql/Node.xml.
- --- The error occurred while preparing the mapped statement for execution.
- --- Check the Node.listNodeByCriteria.
- --- Check the parameter map.
- --- Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list from JavaBean. Cause java.lang.NumberFormatException: For input string: ""
- at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)
- at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
- at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
- at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:212)
- at org.springframework.orm.ibatis.SqlMapClientTemplate.executeWithListResult(SqlMapClientTemplate.java:249)
- at org.springframework.orm.ibatis.SqlMapClientTemplate.queryForList(SqlMapClientTemplate.java:296)
- at com.alibaba.genova.dependency.common.dao.impl.NodeDaoImpl.listNodesByCriteria(NodeDaoImpl.java:116)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
- at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
- at $Proxy8.listNodesByCriteria(Unknown Source)
- at com.alibaba.genova.dependency.common.dao.NodeDAOTest.testListNodeByCriteriaWithNameSpace(NodeDAOTest.java:295)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at junit.framework.TestCase.runTest(TestCase.java:168)
- ... 31 more
- Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:
- --- The error occurred in META-INF/ibatis/mysql/Node.xml.
- --- The error occurred while preparing the mapped statement for execution.
- --- Check the Node.listNodeByCriteria.
- --- Check the parameter map.
- --- Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list from JavaBean. Cause java.lang.NumberFormatException: For input string: ""
- at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:204)
- at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryForList(MappedStatement.java:139)
- at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:567)
- at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:541)
- at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessionImpl.java:118)
- at org.springframework.orm.ibatis.SqlMapClientTemplate$3.doInSqlMapClient(SqlMapClientTemplate.java:298)
- at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:209)
- ... 47 more
- Caused by: com.ibatis.common.beans.ProbeException: Error getting ordinal list from JavaBean. Cause java.lang.NumberFormatException: For input string: ""
- at com.ibatis.common.beans.BaseProbe.getIndexedProperty(BaseProbe.java:86)
- at com.ibatis.common.beans.ComplexBeanProbe.getProperty(ComplexBeanProbe.java:297)
- at com.ibatis.common.beans.ComplexBeanProbe.getObject(ComplexBeanProbe.java:198)
- at com.ibatis.common.beans.GenericProbe.getObject(GenericProbe.java:74)
- at com.ibatis.sqlmap.engine.exchange.ComplexDataExchange.getData(ComplexDataExchange.java:65)
- at com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap.getParameterObjectValues(ParameterMap.java:133)
- at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:181)
- ... 53 more
- Caused by: java.lang.NumberFormatException: For input string: ""
- at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
- at java.lang.Integer.parseInt(Integer.java:470)
- at java.lang.Integer.parseInt(Integer.java:499)
- at com.ibatis.common.beans.BaseProbe.getIndexedProperty(BaseProbe.java:51)
- ... 59 more
这个错误提示真的好烂。被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是DB中的字段名-->
- namespace in
- <!--namespaces是Java代码中Map里面List对应的Key-->
- <iterate property="namespaces" open="(" conjunction="," close=")">
- <!--每一个NameSpace实例的name属性通过namespaces[].name获取-->
- #namespaces[].name#
- </iterate>
这里,回想一下上面列出的简单场景的情况,这种写法也不难理解。
Ibatis中sqlmap参数map中还需要套list的情况如何写?的更多相关文章
- ArcGIS Engine中如何获取Map中已经选择的要素呢(转)
ArcGIS Engine中如何获取Map中已经选择的要素呢 1.使用IEnumFeturea对象获取map中的FeatureSelection,该方法可以获取所有图层的选择要素.IMap中的Fe ...
- Java:TreeMap中LinkedHashMap和Map中HashMap的区别
一般情况下,我们用的最多的是HashMap,在Map 中插入.删除和定位元素,HashMap 是最好的选择. 但如果您要bai按自然顺序或自定义顺序遍历键,那么TreeMap会更好.如果需要输出的顺序 ...
- ArcGIS Engine中如何获取Map中已经选择的要素呢
1.使用IEnumFeturea对象获取map中的FeatureSelection,该方法可以获取所有图层的选择要素.IMap中的FeatureSelection可不是IFeatureSelectio ...
- MyBatis动态SQL使用,传入参数Map中的Key判断
<select id="" parameterType="Map" resultMap="commodityResultMap" &g ...
- js获取url中的参数,url中传递中文的时候通过js解码的方式
如果传递的参数是: <a href="${pageContext.request.contextPath}/productdisplay/productDisplay_productD ...
- 如何在模板中引用参数类中的一个特定member
C++模板有很多特性需要我们去挖掘,很多新的设计模式也都与模板使用相关,我们知道模板的一个基本特性就是可以根据传入的类型产生新的类型.围绕这个特性,可以衍生出很多的其它特性,比如自动为不同的类生成st ...
- C++中如何按照map中的value来进行排序
sort函数无法对map进行排序,网上的方法一般是通过将map转为vector后,再来使用sort进行排序. 如下, 比较函数 bool cmp(const pair<int,int> & ...
- java获取request中的参数、java解析URL问号后的参数
java获取request中的参数.java解析URL问号后的参数.有时候我们需要从request中获取参数,或者获取拼接在Url后面的参数,有时候一个一个去拿有点麻烦,一起拿出来放在一个map里面需 ...
- mybatis从dao传入多个参数到sqlmap时dao中要使用map或实例对象(如:user)作为参数传入, 否则报错找不到属性getter方法
23:37 2015-07-02 注意1. 使用mybaits的resultMap查询时, 如果想传入多个参数(比如where 1=1动态多条件查询时)sqlmap文件中对应的方法中, selectL ...
随机推荐
- oracle 日志学习(转载)
一,重做日志概念 重做日志文件(redo log file)对于Oracle数据库至关重要.它们是数据库的事务日志.通常只用于恢复,不过也可以用于以下工作: q 系统崩溃后的实例恢复 q 通过备份恢复 ...
- EGit插件安装(附Eclipse版本对应表)
最近eclipse添加egit插件,通过网上的方法下载安装后不显示git选项.通过官网了解到egit的版本对应相应的eclipse版本. 如果你安装了最新版本,需要先卸载重启eclipse后重新安装兼 ...
- rx tx
- Tomcat内存溢出的原因
在生产环境中tomcat内存设置不好很容易出现内存溢出.造成内存原因是不一样的,当然处理方式也不一样. 这里根据平时遇到的情况和相关资料进行一个总结.常见的一般会有下面三种情况: 1.OutOfMem ...
- vi / vim 删除以及其它命令
删除一行:dd 删除一个单词/光标之后的单词剩余部分:dw 删除当前字符:x 光标之后的该行部分:d$ 文本删除 dd 删除一行 d$ 删除以当前字符开始的一行字符 ndd 删除以当前行开始的n行 d ...
- 在 windows 上面安装 tensorflow
这个是 tensorflow 官网地址, https://www.tensorflow.org/get_started/os_setup#pip_installation_on_windows 上面有 ...
- java使用xheditor Ajax异步上传错误
java使用xheditor Ajax异步上传时候错误如下:the request doesn't contain a multipart/form-data or multipart/mixed s ...
- RadHat搭建内网YUM源server
前言:随着内网linuxserver越来越多,在每台server上安装软件.都要先把安装盘上传上去.在配置本地yum服务,即麻烦又费时.能够在内网的一台linuxserver上安装yum服务,然后其它 ...
- Java多线程---------同步与死锁:synchronized;等待与唤醒:wait、notify、notifyAll;生命周期
1.问题的引出 class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ ...
- FireMonkey 使用Webbrowser
DELPHI XE5 源码PASCAL:http://files.cnblogs.com/xe2011/FireMonkey_Webbrowser.rar 为了这个用上webbrowser真是费太大劲 ...