報(bào)錯(cuò)日志:
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進(jìn)行查詢操作,按照公司規(guī)范化封裝方式性傳參,一直報(bào)錯(cuò)?。z查傳參類型、參數(shù)名稱都無(wú)誤【o(╥﹏╥)o】
- 實(shí)現(xiàn)類
// IWrapper 參數(shù)是list查詢時(shí),需要封裝兩層
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);
原因:傳參個(gè)數(shù)造成的,需要改變參數(shù)傳入構(gòu)造方式
- 改變實(shí)現(xiàn)類
// IWrapper 單層參數(shù)
public List<IWrapper> list(IWrapper wrapper, String dealStatus) {
return alarmEventMapper.list(wrapper), dealStatus);
}
程序訪問(wèn)沒(méi)有問(wèn)題了。。。Why?頭疼o(╥﹏╥)o
后來(lái)去看了下調(diào)用源碼發(fā)現(xiàn),mybatis在參數(shù)大于一個(gè)時(shí),會(huì)再次封裝參數(shù)為Map!
源碼如下:【重點(diǎn)在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源碼調(diào)流程:

image.png
mybatis在使用Mapper進(jìn)行編程時(shí),其實(shí)際是通過(guò)MybatisMapperProxy代理機(jī)制,調(diào)用的SqlSession對(duì)應(yīng)方法(例如:selectOne(),selectList()),會(huì)把參數(shù)進(jìn)行校驗(yàn)和重新封裝,導(dǎo)致sql執(zhí)行中參數(shù)不一致報(bào)錯(cuò)!
就這么無(wú)厘頭的解決了,O(∩_∩)O哈哈~
參考文獻(xiàn):
https://www.cnblogs.com/zhuyeshen/p/11987696.html
http://www.itdecent.cn/p/742ce60e4c64
附:foreach 參數(shù)及用法
foreach元素的屬性主要有item,index,collection,open,separator,close。
- item:集合中元素迭代時(shí)的別名,該參數(shù)為必選。
- index:在list和數(shù)組中,index是元素的序號(hào),在map中,index是元素的key,該參數(shù)可選
- open:foreach代碼的開(kāi)始符號(hào),一般是(和close=")"合用。常用在in(),values()時(shí)。該參數(shù)可選
- separator:元素之間的分隔符,例如在in()的時(shí)候,separator=","會(huì)自動(dòng)在元素中間用“,“隔開(kāi),避免手動(dòng)輸入逗號(hào)導(dǎo)致sql錯(cuò)誤,如in(1,2,)這樣。該參數(shù)可選。
- close: foreach代碼的關(guān)閉符號(hào),一般是)和open="("合用。常用在in(),values()時(shí)。該參數(shù)可選。
- collection: 要做foreach的對(duì)象,作為入?yún)r(shí),List對(duì)象默認(rèn)用"list"代替作為鍵,數(shù)組對(duì)象有"array"代替作為鍵,Map對(duì)象沒(méi)有默認(rèn)的鍵。當(dāng)然在作為入?yún)r(shí)可以使用@Param("keyName")來(lái)設(shè)置鍵,設(shè)置keyName后,list,array將會(huì)失效