org.apache.ibatis.type.TypeException
问题
根据客户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方法看看。
方法的核心是setNonNullParameter,如图。该方法在BaseTypeHandler是抽象方法,方法实际在LongTypeHandler中,我们看看。
方法的第三个参数是Long型,我们调用时传参是Integer类型,所以就发生了错误。
总结
setParameter方法实际调用的是哪一个TypeHandler是有ParamaterMapping决定的,ParameterMapping又是解析xml得到的,所以如果接口中的类型和xml中的类型不一致,调用方法就会发生类型转换错误。
后面会分析如果xml中不设置ParameterType会发生什么,是否也就有类似的错误出现。