报错日志:
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<IWrapper> list(IWrapper wrapper, String dealStatus) {
return alarmEventMapper.list(wrapper.set("wrapper", IWrapper.create()), dealStatus);
}
- Mapper
List<IWrapper> list(@Param("wrapper") IWrapper wrapper, @Param("wrapper") String dealStatus);
原因:传参个数造成的,需要改变参数传入构造方式
- 改变实现类
// IWrapper 单层参数
public List<IWrapper> 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<String, Object> param = new ParamMap();
int i = 0;
for(Iterator var5 = this.names.entrySet().iterator(); var5.hasNext(); ++i) {
Entry<Integer, String> 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将会失效
网友评论