mybatis-plus 传参报错Type handler was null on parameter mapping for property '__frch_value_0'.

报错日志:

Caused by: org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_value_0'. It was either not specified and/or could not be found for the javaType (com.pajx.pubc.kit.wrapper.IWrapper) : jdbcType (null) combination.
### Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_value_0'. It was either not specified and/or could not be found for the javaType (com.pajx.pubc.kit.wrapper.IWrapper) : jdbcType (null) combination.
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:149)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426)
    ... 120 common frames omitted 

起因:使用foreach进行查询操作,按照公司规范化封装方式性传参,一直报错!!检查传参类型、参数名称都无误【o(╥﹏╥)o】

  • 实现类
       // IWrapper  参数是list查询时,需要封装两层
   public List list(IWrapper wrapper, String dealStatus) {
        return alarmEventMapper.list(wrapper.set("wrapper", IWrapper.create()), dealStatus);
    }
  • Mapper
 List list(@Param("wrapper") IWrapper wrapper, @Param("wrapper") String dealStatus);

原因:传参个数造成的,需要改变参数传入构造方式

  • 改变实现类
    // IWrapper 单层参数
   public List list(IWrapper wrapper, String dealStatus) {
        return alarmEventMapper.list(wrapper), dealStatus);
    }

程序访问没有问题了。。。Why?头疼o(╥﹏╥)o
后来去看了下调用源码发现,mybatis在参数大于一个时,会再次封装参数为Map
源码如下:【重点在else】

  public Object getNamedParams(Object[] args) {                                               
      int paramCount = this.names.size();                                                     
      if (args != null && paramCount != 0) {                                                  
          if (!this.hasParamAnnotation && paramCount == 1) {                                  
              return args[(Integer)this.names.firstKey()];                                    
          } else {                                                                            
              Map param = new ParamMap();                                     
              int i = 0;                                                                      
                                                                                              
              for(Iterator var5 = this.names.entrySet().iterator(); var5.hasNext(); ++i) {    
                  Entry entry = (Entry)var5.next();                          
                  param.put((String)entry.getValue(), args[(Integer)entry.getKey()]);         
                  String genericParamName = "param" + (i + 1);                                
                  if (!this.names.containsValue(genericParamName)) {                          
                      param.put(genericParamName, args[(Integer)entry.getKey()]);             
                  }                                                                           
              }                                                                               
                                                                                              
              return param;                                                                   
          }                                                                                   
      } else {                                                                                
          return null;                                                                        
      }                                                                                       

debugger源码调流程:


image.png

mybatis在使用Mapper进行编程时,其实际是通过MybatisMapperProxy代理机制,调用的SqlSession对应方法(例如:selectOne(),selectList()),会把参数进行校验和重新封装,导致sql执行中参数不一致报错!
就这么无厘头的解决了,O(∩_∩)O哈哈~

参考文献:
https://www.cnblogs.com/zhuyeshen/p/11987696.html
https://www.jianshu.com/p/742ce60e4c64

附:foreach 参数及用法
foreach元素的属性主要有item,index,collection,open,separator,close。

  • item:集合中元素迭代时的别名,该参数为必选。
  • index:在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选
  • open:foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选
  • separator:元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。
  • close: foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。
  • collection: 要做foreach的对象,作为入参时,List对象默认用"list"代替作为键,数组对象有"array"代替作为键,Map对象没有默认的键。当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array将会失效

你可能感兴趣的:(mybatis-plus 传参报错Type handler was null on parameter mapping for property '__frch_value_0'.)