gongstring技术博客
最新文章
源码解读
软件安装
常见问题
大数据
常用工具
鸡汤文
备案号:鄂ICP备15015839号-1
鄂公网安备 42010202001692号
看源码解决:org.apache.ibatis.binding.BindingException: Parameter '0' not found
2020-03-29 22:01:47
作者: gongstring
源码解读
/
看源码解决:org.apache.ibatis.binding.BindingException: Parameter '0' not found
## 报错信息 ``` org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter '0' not found. Available parameters are [arg1, arg0, param1, param2] at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446) at com.sun.proxy.$Proxy98.selectList(Unknown Source) at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:230) at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:137) at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:75) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59) at com.sun.proxy.$Proxy144.getProcessNodeList(Unknown Source) ``` ## 原因分析 1、Mybatis的Mapper类中,参数前面没有添加@Param("xxx")作为参数说明; 2、Mybatis版本升级到了3.4.2以后的版本; ## 解决办法 1、在application.properties(或bootstrap.yml,或配置中心等)中添加如下: ``` mybatis.configuration.use-actual-param-name=false ``` 2、重启应用 ## 源码分析 * mapper.java中接口参数定义有使用如下配置: ``` UserModel findById(Integer id); ``` * mapper.xml中sql语句有使用到如下 ```
SELECT user_id userId,user_name userName FROM demo_user WHERE user_id=#{0} ORDER BY time_created DESC LIMIT 1
``` 关键点:其中参数获取的时候,使用的{0} * org.apache.ibatis.session.Configuration类中 ``` protected boolean useActualParamName = true; ``` 按照源码日志,2016年5月17日的提交记录中,将该参数从原来的false改成了true;猜测是希望在后续版本中减少直接使用{0}、{1}等查询条件,而推荐使用{param1}、{param2}前缀,当然最好是自己写@Param注解声明变量名称。 提交日志见:https://github.com/mybatis/mybatis-3/commit/3f19d04b6ef2a09c452c104d8eb680b37b246b0a#diff-65ade3ef0e889aa04b75e6bb408e3787 * org.apache.ibatis.reflection.ParamNameResolver Mybatis服务在启动的时候,会初始化ParamNameResolver名称转换对象,有关于名称变量定义规则: ``` public ParamNameResolver(Configuration config, Method method) { final Class>[] paramTypes = method.getParameterTypes(); final Annotation[][] paramAnnotations = method.getParameterAnnotations(); final SortedMap
map = new TreeMap
(); int paramCount = paramAnnotations.length; // get names from @Param annotations for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { if (isSpecialParameter(paramTypes[paramIndex])) { // skip special parameters continue; } String name = null; for (Annotation annotation : paramAnnotations[paramIndex]) { if (annotation instanceof Param) { hasParamAnnotation = true; name = ((Param) annotation).value(); break; } } if (name == null) { // @Param was not specified. <-----标记注解不是必须写的 if (config.isUseActualParamName()) { //如果有@Param注解,则优先使用注解名称设置参数值 name = getActualParamName(method, paramIndex); } if (name == null) { // use the parameter index as the name ("0", "1", ...) // gcode issue #71 name = String.valueOf(map.size()); } } map.put(paramIndex, name); } names = Collections.unmodifiableSortedMap(map); } ```