Springboot 集成 Mybatis 处理枚举
mybatis自带了两个处理枚举的 类 EnumTypeHandler ,EnumOrdinalTypeHandler 一个使用枚举的name,一个使用枚举的下标;
做项目时,会节省数据库资源,对一些固定的值,直接在代码里定义为枚举,枚举存放一个code 将这个code存入数据库; 比如男女 存放1 ,0 而不是男女这两个字;
处理这些枚举的时候需要我们自定义枚举处理;
两种实现方案:
定义接口 BaseEnum
public interface BaseEnum {
String getValue();
}
这里定义为String类型;因为在jdbc里面String基本能映射大多数数据库数据类型
也可以使用其他类型
定义枚举类型处理器
/**
* 使用BaseEnum 指定枚举会映射的数据
* @param <E> BaseEnum
* @author jian.jiang
* 处理枚举映射
*/
@MappedTypes(BaseEnum.class)
public class EnumTypeHandler<E extends Enum<E>&BaseEnum> extends BaseTypeHandler<E> {
private final HashMap<String, E> eMap = new HashMap<>();
public EnumTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
for (E e : type.getEnumConstants()) {
eMap.put(e.getValue(), e);
}
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType)
throws SQLException {
if (jdbcType == null)
ps.setString(i, parameter.getValue());
else
ps.setObject(i, parameter.getValue(), jdbcType.TYPE_CODE);
}
@Override
public E getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return eMap.get(rs.getString(columnName));
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return eMap.get(rs.getString(columnIndex));
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return eMap.get(cs.getString(columnIndex));
}
}
更改配置
mybatis:
mapper-locations: classpath:**/mapper/*.xml,classpath:**/dao/*.xml
configuration:
default-enum-type-handler: demo.mybatis.typehandler.EnumTypeHandler
这里的配置default-enum-type-handler会替换掉TypeHandlerRegistry 里面的defaultEnumTypeHandler
枚举定义时实现BaseEnum接口就可以了,例如:
@AllArgsConstructor
@Getter
public enum SexEnum implements BaseEnum {
MAN(1),
WOMAN(0),
UNKNOW(2),
;
@JsonValue
public final Integer code;
@Override
public String getValue() {
return code.toString();
}
}
如果项目中使用rest接口,返回前端时,枚举也需要转为指定的Code,一般会使用@JsonValue注解
可以借助这个注解,省去再写接口,实现接口的步骤
定义枚举处理器
/**
* 与页面vo共用一个注解
* @author jianjiang
*/
public class JsonEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
private final Map<String, E> key2value = new HashMap<>();
private final Map<E, String> value2key = new HashMap<>();
public JsonEnumTypeHandler(Class<E> type) throws IllegalAccessException {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
E[] enumConstants = type.getEnumConstants();
Field[] declaredFields = type.getDeclaredFields();
Field jsonValue = null;
int count = 0;
for (Field e : declaredFields) {
if (e.isAnnotationPresent(JsonValue.class)) {
jsonValue = e;
count++;
}
}
if (count > 1) {
throw new IllegalArgumentException("exist more than one Annotation JsonValue" + type.getName());
} else if (count == 1) {
if (!jsonValue.isAccessible())
jsonValue.setAccessible(true);
for (E e : enumConstants) {
key2value.put(String.valueOf(jsonValue.get(e)), e);
value2key.put(e, String.valueOf(jsonValue.get(e)));
}
} else { //如果没有,按照name进行设置
for (E e : enumConstants) {
key2value.put(e.name(), e);
value2key.put(e, e.name());
}
}
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
if (jdbcType == null) {
ps.setString(i, value2key.get(parameter));
} else {
ps.setObject(i, value2key.get(parameter), jdbcType.TYPE_CODE);
}
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
String s = rs.getString(columnName);
return s == null ? null : key2value.get(s);
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String s = rs.getString(columnIndex);
return s == null ? null : key2value.get(s);
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String s = cs.getString(columnIndex);
return s == null ? null : key2value.get(s);
}
}
配置那替换为这个类