解决过程:
- 一开始以为是项目没有 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;
}
}
至此,则较为完善的解决了该问题。
相关文章
暂无评论...