这里写自定义目录标题
tk.mybatis版本为2.1.15 如何将枚举类型在类中进行自动转换
因为同组的高级开发在搭建项目的时候,引用了tk.mybatis,个人觉得比较小众的mybatis的依赖,构建的springboot。导致tk.mybatis的一些应用没有mybatis-plus灵活方便。个人开发需要了解很多才能进行搭配。
开发过程中,在常用的mybatis-plus中,底层构建了枚举类型的自动转换,所以我们直接引用@EnumValue就可以在枚举类中定义哪些需要再新增和查询的时候,自动进行转换。这个方式比较灵活方便。
直接引用mybaits-plus中的注解@EnumValue
public enum UserTypeEnum {
NON_ADMIN(1, "非管理员"),
ADMIN(2, "管理员"),
;
@EnumValue
private final int code;
private final String type;
UserTypeEnum(int code, String type) {
this.code = code;
this.type = type;
}
public int getCode() {
return code;
}
public String getType() {
return type;
}
}
tk.mybatis 的枚举类型转换问题
1、tk.mybatis的版本是2.1.15,我这边还不能直接动mybatis的版本,因为可能好引起其他的大的问题,所以在网上搜如何配置tk.mybatis的枚举类型自动转换。但是MyBatis中内置有两个枚举转换器分别是:org.apache.ibatis.type.EnumTypeHandler和org.apache.ibatis.type.EnumOrdinalTypeHandler。
2、按照网上的文章进行了配置,自定义了枚举类,但是枚举类型的类依然是报无法转换异常。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author will.smith
* @Date 2023 11 02 17 58
* @Description
**/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnumValue {
}
import com.transsion.datamap.annotion.EnumValue;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.lang.reflect.Field;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @Author will.smith
* @Date 2023 11 02 17 39
* @Description
**/
public class MyEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
private final Class<E> type;
private final E[] enums;
public MyEnumTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
this.enums = type.getEnumConstants();
if (this.enums == null) {
throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
}
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
Field[] declaredFields = parameter.getClass().getDeclaredFields();
for (Field declaredField : declaredFields) {
EnumValue annotation = declaredField.getAnnotation(EnumValue.class);
if (annotation == null) {
continue;
}
declaredField.setAccessible(true);
Object paramValue = null;
try {
// 获取到设置了EnumValue注解字段的value值
paramValue = declaredField.get(parameter);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
ps.setObject(i, paramValue);
return;
}
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
Field[] declaredFields = type.getDeclaredFields();
Field enumField = null;
Object value4Db = null;
for (Field declaredField : declaredFields) {
EnumValue annotation = declaredField.getAnnotation(EnumValue.class);
if (annotation == null) {
continue;
}
enumField = declaredField;
value4Db = rs.getObject(columnName, enumField.getType());
break;
}
if (enumField == null) {
return getResultByOrdinal(rs.getInt(columnName), rs.wasNull());
}
enumField.setAccessible(true);
for (E anEnum : enums) {
try {
Object value = enumField.get(anEnum);
if (value.equals(value4Db)) {
return anEnum;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return getResultByOrdinal(rs.getInt(columnName), rs.wasNull());
}
private E getResultByOrdinal(int anInt, boolean b) {
int ordinal = anInt;
if (ordinal == 0 && b) {
return null;
}
return toOrdinalEnum(ordinal);
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getResultByOrdinal(rs.getInt(columnIndex), rs.wasNull());
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return getResultByOrdinal(cs.getInt(columnIndex), cs.wasNull());
}
private E toOrdinalEnum(int ordinal) {
try {
return enums[ordinal];
} catch (Exception ex) {
throw new IllegalArgumentException("Cannot convert " + ordinal + " to " + type.getSimpleName() + " by ordinal value.", ex);
}
}
}
报错信息
java.lang.IllegalArgumentException: No enum constant com.xxx.xxx.enums.UserType.3
at java.lang.Enum.valueOf(Enum.java:238)
at org.apache.ibatis.type.EnumTypeHandler.getNullableResult(EnumTypeHandler.java:49)
at org.apache.ibatis.type.EnumTypeHandler.getNullableResult(EnumTypeHandler.java:26)
at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:66)
3、后来跟AI搜索发现,原来忘记了在mybatis中要配置mybtis-config.xml;需要在MyBatis配置文件指定哪个类使用我们自己编写转换器进行转换
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 全局参数 -->
<settings>
<!-- 使用驼峰命名法转换字段。 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="SLF4J" />
</settings>
<!--重点在这里,需要在MyBatis配置文件指定哪个类使用我们自己编写转换器进行转换-->
<typeHandlers>
<typeHandler handler="com.xxx.xxx.handler.MyEnumTypeHandler" javaType="com.xxx.xxx.enums.EntityType"/>
</typeHandlers>
</configuration>
最后才解决这个tk.mybatis的枚举类型转换。
欢迎各位技术大佬来提意见,相互交流才是提升自己的一个好的循环的开始。
当前还有一个更好mybatis的枚举类型转换的优化,参考如下:
详情链接如何在MyBatis中优雅的使用枚举
本文参考链接: springboot + mybatis 自定义枚举类型转换.