org.apache.ibatis.type.TypeException
問題
根據(jù)客戶id查詢客戶信息,報出如下錯誤
org.apache.ibatis.type.TypeExceptionCould not set parameters for mapping: ParameterMapping{property='id', mode=IN, javaType=class java.lang.Long, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #1 with JdbcType null
. Cause: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
錯誤堆棧
分析
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
//出錯是在這一行,typeHandler是從parameterMapping取得,是LongTypeHandler
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
} catch (SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
typeHandler是從parameterMapping中取的,是LongTypeHandler類型,我們今setParameter方法看看。
setParameter方法
方法的核心是setNonNullParameter,如圖。該方法在BaseTypeHandler是抽象方法,方法實際在LongTypeHandler中,我們看看。
setNonNullParameter方法
方法的第三個參數(shù)是Long型,我們調(diào)用時傳參是Integer類型,所以就發(fā)生了錯誤。
value是Integer類型
總結(jié)
setParameter方法實際調(diào)用的是哪一個TypeHandler是有ParamaterMapping決定的,ParameterMapping又是解析xml得到的,所以如果接口中的類型和xml中的類型不一致,調(diào)用方法就會發(fā)生類型轉(zhuǎn)換錯誤。
后面會分析如果xml中不設置ParameterType會發(fā)生什么,是否也就有類似的錯誤出現(xiàn)。