Cause: java.lang.IllegalArgumentException: No enum constant com.aliyun.xxx.enums.VersionEnum.2
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73) ~[mybatis-spring-1.2.0.jar:1.2.0]
问题实质是:使用mybatis时查询枚举值字段不能自动装载的问题
一个sql查询,DO中 version 字段为VersionEnum
@Data
@NoArgsConstructor
@JsonInclude(Include.NON_NULL)
public class AlgorithmDO {
@ApiModelProperty(required = true, value = "对象唯一id", example = "123456789")
private Long id;
@ApiModelProperty(required = true, value = "版本", example = "v5")
private VersionEnum version;
但是数据库表中,version 列是VARCHAR(1)
`version` varchar(1) CHARACTER SET utf8 NOT NULL DEFAULT '0' COMMENT '版本',
为version字段,新建 typeHandler, 然后在Map.xml文件中使用typeHandler即可!
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(VersionEnum.class)
public class VersionHandler extends BaseTypeHandler<VersionEnum> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, VersionEnum parameter, JdbcType jdbcType) throws SQLException {
if (ParamValidator.isNotNull(parameter)) {
ps.setString(i, parameter.getCode());
}
}
@Override
public VersionEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
String status = rs.getString(columnName);
return VersionEnum.getEnumByCode(status);
}
@Override
public VersionEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String status = rs.getString(columnIndex);
return VersionEnum.getEnumByCode(status);
}
@Override
public VersionEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String status = cs.getString(columnIndex);
return VersionEnum.getEnumByCode(status);
}
}
resultMap中 ,为version字段指定 javaType(要和哪个枚举类映射) 和 typeHandler (自己新建VersionHandler)
<resultMap id="ModelVOMap" type="com.aliyun.ModelDO">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="version" property="version" jdbcType="VARCHAR" javaType="com.aliyun.VersionEnum" typeHandler="com.aliyun..typehandlers.VersionHandler"/>
resultMap>
内置枚举转换器
首先在MyBatis有两个内置枚举转换器 EnumTypeHandler 和 EnumOrdinalTypeHandler
// mybatis 中默认的枚举转换器,是获取枚举中的 name 属性。
org.apache.ibatis.type.EnumTypeHandler
// 获取枚举中 ordinal 属性,就是例如索引一样的东西,不过是从 1 开始递增的。
org.apache.ibatis.type.EnumOrdinalTypeHandler
因此上面提供的两种的转换器都不能满足我们的需求,我们需要自定义一个转换器。
MyBatis提供了 org.apache.ibatis.type.BaseTypeHandler 类用于我们自己扩展类型转换器,
上面的EnumTypeHandler和EnumOrdinalTypeHandler 也都实现了这个接口。
继承 BaseTypeHandler
一共需要实现4个方法:
void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType)
用于定义设置参数时,该如何把Java类型的参数转换为对应的数据库类型;
T getNullableResult(ResultSet rs, String columnName)
用于定义通过字段名称获取字段数据时,如何把数据库类型转换为对应的Java类型;
T getNullableResult(ResultSet rs, int columnIndex)
用于定义通过字段索引获取字段数据时,如何把数据库类型转换为对应的Java类型;
T getNullableResult(CallableStatement cs, int columnIndex)
用定义调用存储过程后,如何把数据库类型转换为对应的Java类型。
参考文章:https://blog.csdn.net/qq_29864051/article/details/125698196