需求:
在程序中使用枚举(enum) 来表示一些状态或选项,而在数据库中使用数字来存储。这样做的好处是在程序中使用enum更直观的可以知道每个值代表的状态及含义。
分析:
EnumTypeHandler与EnumOrdinalTypeHandler是已经有的两类TypeHandler
两者之间的区别:
EnumTypeHandler存入数据库的是枚举的name,EnumOrdinalTypeHandler存入数据库的是枚举的位置。
例子:
public enum sexEnum implements DemoEnum {
WOMAN(0),MAN(1);
private int code;
private sexEnum(int code){
this.code =code;
}
@Override
public int getValue() {
return code;
}
}
EnumTypeHandler转换获取到的是 WOMAN OR MAN
EnumOrdinalTypeHandler获取到的是 0 OR 1(并非我们上面代码性别枚举中WOMAN()中的数字,只是位置)
因为我们需要自定义一个TypeHandler:
话不多说直接上代码:
1、定义一个接口,作用是在从数据库中获取到值时可以转换
public interface DemoEnum {
int getValue();
}
2、自定义基于BaseTypeHandler的公共类,目的是当你有多个枚举类时解耦,其中的get方法是上一步定义接口的作用:
public class testTypeHandler<E extends Enum<E> & DemoEnum> extends BaseTypeHandler<E> {
private Class<E> type;
private final E[] enums;
public testTypeHandler(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.");
}
}
public E get(int code) {
try {
for(E e:enums) {
if(e.getValue() == code) {
return e;
}
}
} catch (Exception e) {
throw new IllegalArgumentException("erro value!");
}
return null;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i,parameter.getValue());
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
int value = rs.getInt(columnName);
if (rs.wasNull()) {
return null;
}else {
return get(value);
}
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
int value = rs.getInt(columnIndex);
if (rs.wasNull()) {
return null;
}else {
return get(value);
}
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
int value = cs.getInt(columnIndex);
if (cs.wasNull()) {
return null;
}else {
return get(value);
}
}
}
3、新建一个基于上一步基类的公用类,如果你有多个枚举属性需要转换,你可以在MappedTypes注解中增加你的枚举类,目的是不用每次实现一个TypeHandler:
@MappedTypes({sexEnum.class})
public class EnumTypeHandler<E extends Enum<E> & DemoEnum> extends testTypeHandler<E> {
public EnumTypeHandler(Class<E> type) {
super(type);
}
}
4、application.properties中配置
mybatis.type-handlers-package= 你的公共类的包路径
总结:写得可能有点粗糙,希望和大家一起交流。