设为首页 收藏本站
查看: 1091|回复: 0

[经验分享] MyBatis批量操作报错:Parameter 'xxxList' not found. Available parameters are [list]

[复制链接]

尚未签到

发表于 2016-11-28 06:58:11 | 显示全部楼层 |阅读模式
  问题背景:
  在Dao中使用MyBatis进行查询操作,参数是传的一个List:studentNameList,但是在执行查询的时候报错,具体日志如下:

com.chenzhou.base.mybatis.IbatisSystemException: SqlSession operation; nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database.  Cause: org.apache.ibatis.binding.BindingException: Parameter 'studentNameList' not found. Available parameters are

    ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'studentNameList' not found. Available parameters are

      at com.chenzhou.base.mybatis.SqlSessionTemplate.wrapException(SqlSessionTemplate.java:341)
      at com.chenzhou.base.mybatis.SqlSessionTemplate.execute(SqlSessionTemplate.java:127)
      at com.chenzhou.base.mybatis.SqlSessionTemplate.execute(SqlSessionTemplate.java:106)
      at com.chenzhou.base.mybatis.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:138)
      at com.chenzhou.dao.GenericMybatisDao.count(GenericMybatisDao.java:306)
      at com.chenzhou.cds.ps.dao.impl.StudentDao.getStudentCount(StudentDao.java:42)
      at com.chenzhou.cds.ps.dao.impl.StudentDao$$FastClassByCGLIB$$8819e766.invoke(<generated>)
      at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
      at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
      at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80)
      at com.chenzhou.util.LogUtil.doMethodInfo(LogUtil.java:85)
      at com.chenzhou.util.LogUtil.doDebugMethodLog(LogUtil.java:36)
      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.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
      at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
      at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
      at com.chenzhou.cds.ps.dao.impl.StudentDao$$EnhancerByCGLIB$$d4fcf513.getStudentCount(<generated>)
      at com.chenzhou.ps.dao.StudentDaoTest.testgetStudentCount(StudentDaoTest.java:44)
      ……
        单元测试用例代码如下:

      @Test
      public void testgetStudentCount(){
      List<String> studentNameList = new ArrayList<String>();
      studentNameList.add("chenzhou");
      studentNameList.add("zhangsan");
      studentNameList.add("lisi");
      int count = studentDao.getStudentCount(studentNameList);
      System.out.println(count);
      }
        studentDao中的getStudentCount方法代码如下:

      public int getStudentCount(List<String> studentNameList){
      return super.count("getStudentCount", studentNameList);
      }
        MyBatis mapper.xml定义如下:

      <!-- 查询学生数量  -->
      <select id="Student.getStudentCount" parameterType="java.util.List" resultType="java.lang.Integer">
      <![CDATA[
      SELECT
      COUNT(*)
      FROM
      t_student WHERE 1=1
      ]]>
      <if test="studentNameList != null">
      AND student_name in
      <foreach collection="studentNameList" item="item" open="(" separator="," close=")">
      #{item}
      </foreach>
      </if>
      </select>
        根据报错日志分析,是MyBatis在解析xml时找不到其中声明的[size=1em]studentNameList,但是在Dao中明明传的参数就是[size=1em]studentNameList,怎么会报错呢?
        [size=1em]查询了一下MyBatis官方的说明文档,终于找到了原因,在http://mybatis.github.io/mybatis-3/zh/dynamic-sql.html#foreach里有一段说明:

      写道

      注意 你可以传递一个 List 实例或者数组作为参数对象传给 MyBatis。当你这么做的时 候,MyBatis 会自动将它包装在一个 Map 中,用名称在作为键。List 实例将会以“list” 作为键,而数组实例将会以“array”作为键。
        因为我传的参数只有一个,而且传入的是一个List集合,所以mybatis会自动封装成Map<"list",studentNameList>。在解析的时候会通过“list”作为Map的key值去寻找。但是我在xml中却声明成studentNameList了,所以自然会报错找不到。
        解决办法:
        第一种就是修改mapper.xml中foreach标签内容,把studentNameList修改为list

      <if test="list != null">
      AND student_name in
      <foreach collection="list" item="item" open="(" separator="," close=")">
      #{item}
      </foreach>
      </if>
        不过这种方式我个人不太建议,因为以后如果要扩展该方法,增加集合参数的时候,还得修改xml中的内容。
        第二种方式,修改dao中的参数传入方式,手动封装成map,然后把map当参数传进去
        Dao方法修改为:

      public int getStudentCount(List<String> studentNameList){
      //把参数手动封装在Map中
      Map<String, Object> map = new HashMap<String, Object>();
      map.put("studentNameList", studentNameList);
      return super.count("getStudentCount", map);
      }
        然后修改mapper.xml中的parameterType类型为Map

      <!--注意下面的parameterType类型必须修改为Map类型,foreach中引用的List名称不用改变-->
      <select id="Student.getStudentCount" parameterType="java.util.Map" resultType="java.lang.Integer">
      <![CDATA[
      SELECT
      COUNT(*)
      FROM
      t_student WHERE 1=1
      ]]>
      <if test="studentNameList != null">
      AND student_name in
      <foreach collection="studentNameList" item="item" open="(" separator="," close=")">
      #{item}
      </foreach>
      </if>
      </select>
        修改完后,重新执行了一下测试用例,测试通过。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-306297-1-1.html 上篇帖子: redis(五)redis与Mybatis的无缝整合让MyBatis透明的管理缓存二 下篇帖子: 初学者使用MyBatis中遇到的问题
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表