解决过程:
- 一开始以为是项目没有 Install ,尝试 mvn clean install 后仍未解决。
- 尝试断点调试 service 层,但调试始终不进入 service 便直接报错。
- 断点调试 controller 层,可以进入调试 ,但 F5进入 service.xxx 方法则直接报错
- 再次查看代码,发现 mybatis resultType 直接指定实体类对象,中间涉及 数据库类型 转换为 枚举类型
- 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;
  }
}至此,则较为完善的解决了该问题。
相关文章
暂无评论...
 
                             
                         
                            