枚举报错 No enum constant XX 处理方法

3 篇文章 0 订阅
2 篇文章 0 订阅
本文介绍了在MyBatis中遇到枚举转换异常的解决方法,包括修改resultMap配置使用EnumOrdinalTypeHandler,以及由于限制而自定义EnumIntegerTypeHandler的详细步骤,确保数据库与枚举类型的对应,并提供了一个自定义转换器的完整示例。
摘要由CSDN通过智能技术生成

解决过程:

  1. 一开始以为是项目没有 Install ,尝试 mvn clean install 后仍未解决。
  2. 尝试断点调试 service 层,但调试始终不进入 service 便直接报错。
  3. 断点调试 controller 层,可以进入调试 ,但 F5进入 service.xxx 方法则直接报错
  4. 再次查看代码,发现 mybatis resultType 直接指定实体类对象,中间涉及 数据库类型 转换为 枚举类型
  5. mybatis 默认使用转换器EnumTypeHandler 进行转换,类型为字符串。

解决方法:

修改 mybatis xml文件,将 resultType 修改为 resultMap配置,根据字段需要指定转换类为EnumOrdinalTypeHandler (前提条件为 enum 中下标key必须从0开始,且数据库与之对应,否则则会出现数组越界错误 由此可见,此类型处理器适用性不广,建议自己重写一个通用的 int to enum EnumIntegerTypeHandler)

示例如下:

<resultMap id="queryXXXResultMap" type="com.test.bean.XXX">
  <result column="columnName" property="propertyName"
    typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
</resultMap>

<select id="queryXXX" resultMap="queryXXXResultMap">
  select
    id,
    name
  from
    xxx_table
</select>

补充:

如果本身就是 resultMap 配置了多个字段,只涉及其中个别字段需要 枚举转换则 只需要在对应列上 添加 typeHandler 属性

以上方法前提条件为 enum 中下标key必须从0开始,且数据库与之对应,否则则会出现数组越界错误 由此可见,此类型处理器适用性不广,建议自己重写一个通用的 int to enum EnumIntegerTypeHandler

自定义整型转换为枚举类型处理器:

1. 定义获取枚举整型key接口

/**
 * 获取枚举整型key接口 在需要使用 EnumIntegerTypeHandler 类型处理器的 enum 上 implements EnumIntegerKeyInterface 类
 * 并实现其方法 示例:com.huayizhe.pojo.eu.ItemCommentLevelEnum
 *
 * @author HuaYiZhe
 * @date 2022/3/18 1:10
 * @since v1.0.0
 */
public interface EnumIntegerKeyInterface {

  /**
   * 获取枚举 key
   *
   * @return 枚举的 key
   */
  Integer getEnumIntegerKey();
}

2. 整型转换为枚举类型处理器

/**
 * 自定义整型转换为枚举类型处理器 在需要使用该类型处理器的 enum 上 implements EnumIntegerKeyInterface 类 并实现其方法
 * 示例:com.huayizhe.pojo.eu.ItemCommentLevelEnum
 *
 * @author HuaYiZhe
 * @date 2022/3/18 1:12
 * @since v1.0.0
 */
public class EnumIntegerTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {

  /** 枚举类型 */
  private final Class<E> type;

  /** 使用 map 类型代替 EnumOrdinalTypeHandler 中 E[] enums 枚举数组, 解决 enum key 未从0开始的问题 */
  private final Map<Integer, E> enumMap = new HashMap<>();

  public EnumIntegerTypeHandler(Class<E> type) {
    if (type == null) {
      throw new IllegalArgumentException("Type argument cannot be null");
    }

    // 初始化枚举类型
    this.type = type;
    // 按顺序获取枚举类型
    E[] enums = type.getEnumConstants();
    if (enums == null) {
      throw new IllegalArgumentException(
          type.getSimpleName() + " does not represent an enum type.");
    }
    // 遍历枚举类型
    for (E e : enums) {
      // 将枚举转换为 EnumIntegerKeyInterface 类型,调用其 getEnumIntegerKey 方法获取枚举 key 作为 enumMap的 key
      EnumIntegerKeyInterface enumIntegerKeyInterface = (EnumIntegerKeyInterface) e;
      this.enumMap.put(enumIntegerKeyInterface.getEnumIntegerKey(), e);
    }
  }

  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType)
      throws SQLException {
    // 将枚举转换为 EnumIntegerKeyInterface 类型 并设置参数
    EnumIntegerKeyInterface enumIntegerKeyInterface = (EnumIntegerKeyInterface) parameter;
    ps.setInt(i, enumIntegerKeyInterface.getEnumIntegerKey());
  }

  @Override
  public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
    int key = rs.getInt(columnName);
    if (key == 0 && rs.wasNull()) {
      return null;
    }
    return getIntegerEnum(key);
  }

  @Override
  public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    int key = rs.getInt(columnIndex);
    if (key == 0 && rs.wasNull()) {
      return null;
    }
    return getIntegerEnum(key);
  }

  @Override
  public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    int key = cs.getInt(columnIndex);
    if (key == 0 && cs.wasNull()) {
      return null;
    }
    return getIntegerEnum(key);
  }

  /**
   * @param key 数据库值 对应的枚举 key
   * @return 对应的枚举类型
   */
  private E getIntegerEnum(int key) {
    try {
      return this.enumMap.get(key);
    } catch (Exception ex) {
      throw new IllegalArgumentException(
          "Cannot convert " + key + " to " + type.getSimpleName() + " by value.", ex);
    }
  }
}
/**
 * 商品评论等级枚举
 *
 * @author HuaYiZhe
 * @date 2021/4/5 17:06
 * @since v1.0.0
 */
public enum ItemCommentLevelEnum implements EnumIntegerKeyInterface {
  GOOD(1, "好评"),
  NORMAL(2, "中评"),
  BAD(3, "差评");

  public final Integer key;
  public final String value;

  ItemCommentLevelEnum(Integer key, String value) {
    this.key = key;
    this.value = value;
  }

  @Override
  public Integer getEnumIntegerKey() {
    return this.key;
  }
}

至此,则较为完善的解决了该问题。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值