Type handler was null on parameter mapping for property 'version'
Question
我在程序里设置了Version对应的TypeHandler,但是在运行的时候却老是报错:Type handler was null on parameter mapping for property 'version'
VersionTypeHandler.groovy
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(Version.class)
class VersionTypeHandler extends BaseTypeHandler<Version> {
@Override
void setNonNullParameter(PreparedStatement ps, int i, Version v, JdbcType jdbcType) throws SQLException {
ps.setString(i, v.toString())
}
@Override
Version getNullableResult(ResultSet rs, String columnName) throws SQLException {
def value = rs.getString(columnName)
return Version.from(value)
}
@Override
Version getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
def value = rs.getString(columnIndex)
return Version.from(value)
}
@Override
Version getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
def value = cs.getString(columnIndex)
return Version.from(value)
}
}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<package name="com.xxx.core.domain"/>
<package name="com.xxx.admin.domain"/>
</typeAliases>
<typeHandlers>
<typeHandler handler="com.xxx.core.mybatis.ImagesTypeHandler"/>
<typeHandler handler="com.xxx.core.mybatis.PricesTypeHandler"/>
<typeHandler handler="com.xxx.core.mybatis.BoughtsTypeHandler"/>
<typeHandler handler="com.xxx.core.mybatis.VersionTypeHandler"/>
<typeHandler handler="com.xxx.core.mybatis.MessageDataHandler"/>
</typeHandlers>
<plugins>
<plugin interceptor="com.xxx.core.mybatis.StatsInterceptor"/>
</plugins>
<mappers>
<package name="com.xxx.core.mapper"/>
<package name="com.xxx.admin.mapper"/>
</mappers>
</configuration>
Answer
通过Google搜索了一圈,发现并不能解决我目前遇到的问题,于是就跑到MyBatis官方文档去看,详细一看之后发现了问题:
When deciding which TypeHandler to use in a ResultMap, the Java type is known (from the result type), but the JDBC type is unknown. MyBatis therefore uses the combination
javaType=[TheJavaType], jdbcType=null
to choose a TypeHandler. This means that using a @MappedJdbcTypes annotation restricts the scope of a TypeHandler and makes it unavailable for use in ResultMaps unless explicity set. To make a TypeHandler available for use in a ResultMap, setincludeNullJdbcType=true
on the @MappedJdbcTypes annotation. Since Mybatis 3.4.0 however, if a single TypeHandler is registered to handle a Java type, it will be used by default in ResultMaps using this Java type (i.e. even without includeNullJdbcType=true).
文档其实说得很明确了,只需要添加includeNullJdbcType=true
这个属性就可以解决。但是v3.4.0以后,就不需要显式的添加这个属性了。
修改之后的VersionTypeHandler.groovy
@MappedJdbcTypes(value=JdbcType.VARCHAR, includeNullJdbcType = true)
@MappedTypes(Version.class)
class VersionTypeHandler extends BaseTypeHandler<Version> {
@Override
void setNonNullParameter(PreparedStatement ps, int i, Version v, JdbcType jdbcType) throws SQLException {
ps.setString(i, v.toString())
}
@Override
Version getNullableResult(ResultSet rs, String columnName) throws SQLException {
def value = rs.getString(columnName)
return Version.from(value)
}
@Override
Version getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
def value = rs.getString(columnIndex)
return Version.from(value)
}
@Override
Version getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
def value = cs.getString(columnIndex)
return Version.from(value)
}
}