解决 mybatis:Cause: java.lang.IllegalArgumentException: No enum constant com.xxxEnum

异常信息如下:

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即可!

新建VersionHandler继承BaseTypeHandler


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);
    }
}

在Map.xml文件中使用typeHandler

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值